diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 6320a134..00000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "starlight-devcontainer", - "image": "mcr.microsoft.com/devcontainers/base:ubuntu", // Any generic, debian-based image. - "features": { - "ghcr.io/devcontainers/features/java:1": { - "version": "8", - "jdkDistro": "tem", - "installMaven": true - } - } -} \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index ded0100f..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 0886c3e8..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "maven" - directory: "/starlight" - schedule: - interval: "weekly" - - package-ecosystem: "maven" - directory: "/spring-cloud-starter-baidu-starlight" - schedule: - interval: "weekly" \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 2cf8f8de..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ "main" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "main" ] - schedule: - - cron: '26 21 * * 1' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-20.04 - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'java' ] - java: [ '8', '17' ] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Setup Java JDK and Maven - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: Build starlight - if: ${{ matrix.java == '8' }} - run: | - mvn -B clean package -Dmaven.test.skip --file starlight/pom.xml --no-transfer-progress - - - name: Build starlight-starter - if: ${{ matrix.java == '17' }} - run: | - mvn -B clean package -Dmaven.test.skip --file spring-cloud-starter-baidu-starlight/pom.xml --no-transfer-progress - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml deleted file mode 100644 index 9bd426ea..00000000 --- a/.github/workflows/snapshot.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Snapshot -on: - push: - branches: [ "main" ] - -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - java: [ '8', '17' ] - steps: - - name: Checkout project - uses: actions/checkout@v3 - - - name: Setup Java JDK and Maven - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.GPG_SECRET }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Configure Git user - run: | - git config user.email "actions@github.com" - git config user.name "GitHub Actions" - - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: Publish Snaphot package starlight - if: ${{ matrix.java == '8' }} - run: | - mvn -B deploy -P deploy -Dmaven.test.skip --file starlight/pom.xml --no-transfer-progress - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAVEN_USERNAME: ${{ secrets.OSSRH_USER }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWD }} - - - name: Publish Snaphot package starlight-starter - if: ${{ matrix.java == '17' }} - run: | - mvn -B deploy -P deploy -Dmaven.test.skip --file spring-cloud-starter-baidu-starlight/pom.xml --no-transfer-progress - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAVEN_USERNAME: ${{ secrets.OSSRH_USER }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWD }} diff --git a/.github/workflows/starlight-release.yml b/.github/workflows/starlight-release.yml deleted file mode 100644 index 038a2808..00000000 --- a/.github/workflows/starlight-release.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Starlight Release - -on: - workflow_dispatch: - inputs: - releaseVersion: - description: "Default version to use when preparing a release." - required: true - default: "X.Y.Z" - developmentVersion: - description: "Default version to use for new local working copy." - required: true - default: "X.Y.Z-SNAPSHOT" - - -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - name: Checkout project - uses: actions/checkout@v3 - - - name: Setup Java JDK and Maven - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '8' - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.GPG_SECRET }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Configure Git user - run: | - git config user.email "actions@github.com" - git config user.name "GitHub Actions" - - - name: Publish package - run: | - cd starlight - mvn -B release:prepare release:perform -P deploy -Darguments="-Dmaven.test.skip" -DreleaseVersion=${{ github.event.inputs.releaseVersion }} -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} --no-transfer-progress - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAVEN_USERNAME: ${{ secrets.OSSRH_USER }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWD }} - - - name: Generate changelog - id: changelog - uses: metcalfc/changelog-generator@v4.0.1 - with: - myToken: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitHub Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: starlight-v${{ github.event.inputs.releaseVersion }} - release_name: starlight-v${{ github.event.inputs.releaseVersion }} - body: | - ### Things that changed in this release - ${{ steps.changelog.outputs.changelog }} - draft: true - prerelease: false diff --git a/.github/workflows/starlight-starter-release.yml b/.github/workflows/starlight-starter-release.yml deleted file mode 100644 index b4040af1..00000000 --- a/.github/workflows/starlight-starter-release.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Starlight Starter Release - -on: - workflow_dispatch: - inputs: - releaseVersion: - description: "Default version to use when preparing a release." - required: true - default: "X.Y.Z" - developmentVersion: - description: "Default version to use for new local working copy." - required: true - default: "X.Y.Z-SNAPSHOT" - - -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - name: Checkout project - uses: actions/checkout@v3 - - - name: Setup Java JDK and Maven - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '17' - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.GPG_SECRET }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Configure Git user - run: | - git config user.email "actions@github.com" - git config user.name "GitHub Actions" - - - name: Publish package - run: | - cd spring-cloud-starter-baidu-starlight - mvn -B release:prepare release:perform -P deploy -Darguments="-Dmaven.test.skip" -DreleaseVersion=${{ github.event.inputs.releaseVersion }} -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} --no-transfer-progress - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAVEN_USERNAME: ${{ secrets.OSSRH_USER }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWD }} - - - name: Generate changelog - id: changelog - uses: metcalfc/changelog-generator@v4.0.1 - with: - myToken: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitHub Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: starter-v${{ github.event.inputs.releaseVersion }} - release_name: starter-v${{ github.event.inputs.releaseVersion }} - body: | - ### Things that changed in this release - ${{ steps.changelog.outputs.changelog }} - draft: true - prerelease: false diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml deleted file mode 100644 index 5ec129c7..00000000 --- a/.github/workflows/unit-test.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Unit Test - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - build: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - java: [ '8', '17' ] - steps: - - name: Checkout project - uses: actions/checkout@v3 - - - name: Setup Java JDK and Maven - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: Build starlight - if: ${{ matrix.java == '8' }} - run: | - mvn -B verify --file starlight/pom.xml --no-transfer-progress - - - name: Build starlight-starter - if: ${{ matrix.java == '17' }} - run: | - mvn -B verify --file spring-cloud-starter-baidu-starlight/pom.xml --no-transfer-progress - - - name: Upload Coverage Report - uses: codecov/codecov-action@v3 diff --git a/.gitignore b/.gitignore index 037b7b73..b6d91100 100644 --- a/.gitignore +++ b/.gitignore @@ -1,86 +1,26 @@ -############################## -## Java -############################## -.mtj.tmp/ -*.class -*.jar -*.war -*.ear -*.nar -hs_err_pid* - -############################## -## Maven -############################## -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -pom.xml.bak -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar - -############################## -## Gradle -############################## -bin/ -build/ -.gradle -.gradletasknamecache -gradle-app.setting -!gradle-wrapper.jar - -############################## -## IntelliJ -############################## -out/ -.idea/ -.idea_modules/ -*.iml -*.ipr -*.iws - -############################## -## Eclipse -############################## -.settings/ -bin/ -tmp/ -.metadata +*.swp +*.swo +target .classpath .project -*.tmp -*.bak -*.swp -*~.nib -local.properties -.loadpath -.factorypath - -############################## -## NetBeans -############################## -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -nbactions.xml -nb-configuration.xml - -############################## -## Visual Studio Code -############################## -.vscode/ -.code-workspace - -############################## -## OS X -############################## +.settings +.svn +output +.idea +*.iml +*.pyc +logs/ +*MANIFEST +*artifacts .DS_Store - -.sdkmanrc \ No newline at end of file +BaiduRpcErrno.java +Options.java +StreamingRpcProto.java +SofaRpcProto.java +BaiduRpcProto.java +Echo.java +HuluRpcProto.java +brpc-java-core/.factorypath +brpc-java-examples/.factorypath +brpc-java-spring/.factorypath +PublicPbrpcProto.java diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..1ef8d698 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.4"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + " .jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..1914b842 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..05c741ea --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..5b3d2f67 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: java +sudo: false + +cache: + directories: + - $HOME/.m2 + +install: true + +script: + - travis_wait 30 ./mvnw clean install diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 18c91471..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/LICENSE b/LICENSE index d52863d0..07a8a7e8 100644 --- a/LICENSE +++ b/LICENSE @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/README.md b/README.md index fe6a957f..7eb046ba 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,117 @@ -[![GitHub license](https://img.shields.io/github/license/baidu/starlight?style=social)](https://github.com/baidu/starlight/blob/main/LICENSE) -[![GitHub stars](https://img.shields.io/github/stars/baidu/starlight?style=social)](https://github.com/baidu/starlight/stargazers) -[![GitHub issues](https://img.shields.io/github/issues/baidu/starlight?style=social)](https://github.com/baidu/starlight/issues) -[![Codecov branch](https://img.shields.io/codecov/c/gh/baidu/starlight/main?style=social)](https://codecov.io/gh/baidu/starlight) +[![Build Status](https://travis-ci.org/baidu/brpc-java.svg?branch=master)](https://travis-ci.org/baidu/brpc-java) +![license](https://img.shields.io/github/license/baidu/brpc-java.svg) +![maven](https://img.shields.io/maven-central/v/com.baidu/brpc-java.svg) -| GroupId | ArtifactId | Snapshot Version | Stable Version | -|---------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -|com.baidu.cloud| starlight-all | [![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/com.baidu.cloud/starlight-all?server=https%3A%2F%2Foss.sonatype.org&style=social)](https://oss.sonatype.org/content/repositories/snapshots/com/baidu/cloud/starlight-all/) | [![Maven Central](https://img.shields.io/maven-central/v/com.baidu.cloud/starlight-all?style=social)](https://repo.maven.apache.org/maven2/com/baidu/cloud/starlight-all/) | -|com.baidu.cloud| spring-cloud-starter-baidu-starlight | [![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/com.baidu.cloud/spring-cloud-starter-baidu-starlight?server=https%3A%2F%2Foss.sonatype.org&style=social)](https://oss.sonatype.org/content/repositories/snapshots/com/baidu/cloud/spring-cloud-starter-baidu-starlight/) | [![Maven Central](https://img.shields.io/maven-central/v/com.baidu.cloud/spring-cloud-starter-baidu-starlight?style=social)](https://repo.maven.apache.org/maven2/com/baidu/cloud/spring-cloud-starter-baidu-starlight/) | +# 项目名称 +brpc-java是baidu rpc的java版本实现,支持baidu rpc、nshead、sofa、hulu、http、stargate等协议。 -# Starlight: Lightweight Java RPC Framework -Starlight 是一套面向云原生的微服务通信框架,兼容Spring生态,基于此可快速构建高效、稳定、可控、可观测的微服务应用,获得研发效率提升、业务稳定性增强等舒适体验。 -核心特性如下: -* 多种协议支持:Starlight单端口支持[brpc](https://github.com/apache/incubator-brpc)、Spring MVC REST协议,提供超丰富的使用场景 -* 高性能远程通信:Starlight基于多路复用的NIO框架封装底层通信能力,提供高性能高并发网络通信能力 -* 易于使用:无需处理protobuf编译过程,通过原生Java接口和POJO对象加上类级别的注解,类似Java RMI和Spring MVC使用体验,即可实现brpc二进制协议的Server和Client;支持无损升级、异常实例摘除;规范化的日志可以秒级定位超时问题、序列化失败问题 +# 核心功能点 +* 支持baidu rpc标准协议、sofa协议、hulu协议、nshead+protobuf协议、http+protobuf/json协议、public pbrpc、stargate协议。 +* 支持SpringBoot starter,也支持SpringCloud的服务注册发现、用brpc-java替换Feign http调用,提升性能。 +* 支持Server Push机制,并支持扩展Server Push协议。 +* 支持多种naming服务,比如Zookeeper、Consul、List、File、DNS等,可以灵活扩展支持etcd、eureka、nacos等。 +* 支持多种负载均衡策略,比如fair、random、round robin、weight等。 +* 支持interceptor功能,支持计数器、令牌桶等server端限流算法。 +* rpc功能可独立使用,不是必须依赖Spring和注册中心功能。 +* 基于SPI机制可灵活扩展Protocol、NamingService和LoadBalance。 -详细使用和设计文档参见[Github Wiki](https://github.com/baidu/starlight/wiki) +## 快速开始 +### 开发环境 +java 6+ && netty 4 && protobuf 2.5.0 -## JDK Requirements -minimum JDK 8 +### 引入maven依赖 +非Spring环境: +```xml + + com.baidu + brpc-java + 2.5.8 + +``` +Spring环境: +```xml + + com.baidu + brpc-spring + 2.5.8 + +``` +SpringBoot环境: +```xml + + com.baidu + brpc-spring-boot-starter + 2.5.8 + +``` +SpringCloud环境: +```xml + + com.baidu + spring-cloud-brpc + 2.5.8 + +``` +Zookeeper注册中心: +```xml + + com.baidu + brpc-java-naming-zookeeper + 2.5.8 + +``` +Consul注册中心: +```xml + + com.baidu + brpc-java-naming-consul + 2.5.8 + +``` +### Server端使用 +* [server端基本用法](https://github.com/baidu/brpc-java/blob/master/docs/cn/server.md) +* [搭建标准协议/sofa协议/hulu协议server](https://github.com/baidu/brpc-java/blob/master/docs/cn/brpc_server.md) +* [搭建nshead server](https://github.com/baidu/brpc-java/blob/master/docs/cn/nshead_server.md) +* [搭建http server](https://github.com/baidu/brpc-java/blob/master/docs/cn/http_server.md) +* [server push 推送用法](https://github.com/baidu/brpc-java/blob/master/docs/cn/server_push.md) -## License -baidu/starlight is licensed under the Apache License 2.0 +### Client端使用 +* [client端基本用法](https://github.com/baidu/brpc-java/blob/master/docs/cn/client.md) -![Comate PowerSource Initiative Logo](https://comate.baidu.com/images/powersource/powersource-dark-en-5.png) +### 与Spring集成 +* [Spring集成使用](https://github.com/baidu/brpc-java/blob/master/docs/cn/spring.md) + +### 扩展 +* [扩展Protocol、NamingService、LoadBalance](https://github.com/baidu/brpc-java/blob/master/docs/cn/extension.md) + +### 一些设计 +#### 网络模型 +采用netty的reactor网络模型,但跟常规用法有些不同: +* 没有使用netty的ByteToMessageDecoder去解析协议,因为ByteToMessageDecoder内部会对buffer进行拷贝。 +* 为了提高并发,尽量少在IO线程中执行业务逻辑,所以在io线程中只会去解析协议的header部分,并把body的buffer retain出来,然后丢给工作线程去处理;工作线程会decode body,并执行具体业务逻辑。 +* 由于粘包/拆包问题,可能一次socket读操作会包含多个包,所以支持了批量往工作线程中submit任务。 + +#### 零拷贝Buffer +* [DynamicCompositeByteBuf](https://github.com/baidu/brpc-java/blob/master/docs/cn/composite_buffer.md) + +#### 线程池ThreadPool +* 调研过JDK的ThreadPoolExecutor、ConcurrentLinkedQueue以及Disruptor,最后使用更高性能的[ThreadPool]( +https://github.com/baidu/brpc-java/blob/master/brpc-java-core/src/main/java/com/baidu/brpc/utils/ThreadPool.java)。 +* ThreadPool内部把生产者队列、消费者队列分开,用两个锁去控制同步,当consumer queue为空时,且producer queue不为空条件满足时,会交换两个队列。 + +#### 比ConcurrentHashMap更快的FastFutureStore +* [FastFutureStore](https://github.com/baidu/brpc-java/blob/master/docs/cn/fastfuturestore.md) + +## 压力测试数据 +### 部署环境: +* Client/Server机器配置:cpu 12核,内存132G,千兆网卡。 +* [压测代码](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/src/main/java/com/baidu/brpc/example/standard/BenchmarkTest.java) +### 压力测试结果: +| 数据量 | 5 byte | 1k byte | 2k byte | 4k byte | +|:-----:| :-----: | :-------: | :-------: | :-------: | +|qps | 22w | 10w | 5.3w | 2.7w | + +# 微信交流群: + -# 微信交流群 -添加管理员olivaw2077帮忙加群,备注starlight - diff --git a/brpc-java-core/pom.xml b/brpc-java-core/pom.xml new file mode 100644 index 00000000..1aaf30b5 --- /dev/null +++ b/brpc-java-core/pom.xml @@ -0,0 +1,136 @@ + + + + 4.0.0 + + + com.baidu + brpc-java-parent + 2.5.9 + + + brpc-java + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + io.netty + netty-all + + + com.google.protobuf + protobuf-java + + + com.googlecode.protobuf-java-format + protobuf-java-format + + + com.baidu + jprotobuf + + + org.slf4j + slf4j-api + + + cglib + cglib + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-collections4 + + + org.apache.commons + commons-pool2 + + + org.projectlombok + lombok + provided + + + com.google.code.gson + gson + + + javax.servlet + javax.servlet-api + + + org.xerial.snappy + snappy-java + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + com.dyuproject.protostuff + protostuff-runtime + 1.0.7 + + + com.dyuproject.protostuff + protostuff-api + 1.0.7 + + + com.dyuproject.protostuff + protostuff-collectionschema + 1.0.7 + + + com.dyuproject.protostuff + protostuff-core + 1.0.7 + + + + diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/ChannelInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/ChannelInfo.java new file mode 100644 index 00000000..818f9d67 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/ChannelInfo.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.FastFutureStore; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.Response; + +import io.netty.channel.Channel; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Setter +@Getter +@Slf4j +public class ChannelInfo { + private static final AttributeKey CLIENT_CHANNEL_KEY = AttributeKey.valueOf("client_key"); + private static final AttributeKey SERVER_CHANNEL_KEY = AttributeKey.valueOf("server_key"); + + private Channel channel; + private BrpcChannel channelGroup; + private Protocol protocol; + private long correlationId; + private FastFutureStore pendingRpc; + private DynamicCompositeByteBuf recvBuf = new DynamicCompositeByteBuf(16); + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public static ChannelInfo getOrCreateClientChannelInfo(Channel channel) { + Attribute attribute = channel.attr(ChannelInfo.CLIENT_CHANNEL_KEY); + ChannelInfo channelInfo = attribute.get(); + if (channelInfo == null) { + channelInfo = new ChannelInfo(); + // 此时FastFutureStore单例对象已经在RpcClient创建时初始化过了 + channelInfo.setPendingRpc(FastFutureStore.getInstance(0)); + channelInfo.setChannel(channel); + attribute.set(channelInfo); + } + return channelInfo; + } + + public static ChannelInfo getClientChannelInfo(Channel channel) { + Attribute attribute = channel.attr(ChannelInfo.CLIENT_CHANNEL_KEY); + return attribute.get(); + } + + public static ChannelInfo getOrCreateServerChannelInfo(Channel channel) { + Attribute attribute = channel.attr(ChannelInfo.SERVER_CHANNEL_KEY); + ChannelInfo channelInfo = attribute.get(); + if (channelInfo == null) { + channelInfo = new ChannelInfo(); + channelInfo.setChannel(channel); + attribute.set(channelInfo); + } + return channelInfo; + } + + public static ChannelInfo getServerChannelInfo(Channel channel) { + Attribute attribute = channel.attr(ChannelInfo.SERVER_CHANNEL_KEY); + return attribute.get(); + } + + public long addRpcFuture(RpcFuture future) { + // FastFutureStore会保证返回的logId不会占用已经使用过的slot + return pendingRpc.put(future); + } + + public RpcFuture getRpcFuture(long correlationId) { + return pendingRpc.get(correlationId); + } + + public RpcFuture removeRpcFuture(long correlationId) { + return pendingRpc.getAndRemove(correlationId); + } + + /** + * return channel when fail + * + * @param channelType + */ + public void handleRequestFail(ChannelType channelType, long correlationId) { + removeRpcFuture(correlationId); + if (channelType == ChannelType.SHORT_CONNECTION) { + channel.close(); + channelGroup.close(); + } else { + channelGroup.incFailedNum(); + returnChannelAfterRequest(channelType); + } + } + + /** + * return channel when success + */ + public void handleRequestSuccess(ChannelType channelType) { + returnChannelAfterRequest(channelType); + } + + private void returnChannelAfterRequest(ChannelType channelType) { + if (channelType != ChannelType.SHORT_CONNECTION && protocol.returnChannelBeforeResponse()) { + channelGroup.returnChannel(channel); + } + } + + /** + * return channel when fail + */ + public void handleResponseFail() { + channelGroup.incFailedNum(); + returnChannelAfterResponse(); + } + + /** + * return channel when success + */ + public void handleResponseSuccess() { + returnChannelAfterResponse(); + } + + private void returnChannelAfterResponse() { + if (!protocol.returnChannelBeforeResponse()) { + channelGroup.returnChannel(channel); + } + } + + /** + * channel不可用时或者handler出现异常时处理逻辑 + */ + public void handleChannelException(RpcException ex) { + if (channelGroup != null) { + channelGroup.removeChannel(channel); + } + // 遍历并删除当前channel下所有RpcFuture + pendingRpc.traverse(new ChannelErrorStoreWalker(channel, ex)); + } + + public void close() { + log.debug("close the channel:{}", channel); + channel.close(); + } + + protected ChannelInfo() { + } + + /** + * 用于遍历FutureStore元素的实现类 + */ + private static class ChannelErrorStoreWalker implements FastFutureStore.StoreWalker { + private Channel currentChannel; + private RpcException exception; + + public ChannelErrorStoreWalker(Channel currentChannel, RpcException exception) { + this.currentChannel = currentChannel; + this.exception = exception; + } + + @Override + public boolean visitElement(RpcFuture fut) { + // 与当前channel相同则删除 + ChannelInfo chanInfo = fut.getChannelInfo(); + if (null == chanInfo) { + return true; + } + + // 不删除返回true + return currentChannel != chanInfo.channel; + } + + @Override + public void actionAfterDelete(RpcFuture fut) { + Response response = fut.getRpcClient().getProtocol().createResponse(); + response.setException(exception); + response.setRpcFuture(fut); + fut.handleResponse(response); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/JprotobufRpcMethodInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/JprotobufRpcMethodInfo.java new file mode 100644 index 00000000..1d25ae25 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/JprotobufRpcMethodInfo.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.baidu.bjf.remoting.protobuf.Codec; +import com.baidu.bjf.remoting.protobuf.ProtobufProxy; +import com.google.protobuf.CodedOutputStream; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +import java.io.IOException; +import java.lang.reflect.Method; + +/** + * jprotobuf method info, which can be encode/decode jprotobuf class. + * details for jprotobuf: https://github.com/jhunters/jprotobuf + */ +@Setter +@Getter +public class JprotobufRpcMethodInfo extends RpcMethodInfo { + private Codec inputCodec; + private Codec outputCodec; + + public JprotobufRpcMethodInfo(Method method) { + super(method); + inputCodec = ProtobufProxy.create((Class) (inputClasses[0])); + outputCodec = ProtobufProxy.create((Class) outputClass); + } + + @Override + public byte[] inputEncode(Object input) throws IOException { + if (inputCodec != null) { + return inputCodec.encode(input); + } + return null; + } + + @Override + public void inputWriteToStream(Object input, CodedOutputStream stream) throws IOException { + if (inputCodec != null) { + inputCodec.writeTo(input, stream); + } + } + + @Override + public Object outputDecode(byte[] output) throws IOException { + if (outputCodec != null) { + return outputCodec.decode(output); + } + return null; + } + + @Override + public Object outputDecode(ByteBuf output) throws IOException { + if (outputCodec != null) { + int len = output.readableBytes(); + byte[] bytes = new byte[len]; + output.readBytes(bytes); + return outputCodec.decode(bytes); + } + return null; + } + + @Override + public Object outputDecode(DynamicCompositeByteBuf output) throws IOException { + if (outputCodec != null) { + int len = output.readableBytes(); + byte[] bytes = new byte[len]; + output.readBytes(bytes); + return outputCodec.decode(bytes); + } + return null; + } + + @Override + public Object inputDecode(byte[] input) throws IOException { + if (inputCodec != null) { + return inputCodec.decode(input); + } + return null; + } + + @Override + public Object inputDecode(ByteBuf input) throws IOException { + if (inputCodec != null) { + int len = input.readableBytes(); + byte[] bytes = new byte[len]; + input.readBytes(bytes); + return inputCodec.decode(bytes); + } + return null; + } + + @Override + public Object inputDecode(DynamicCompositeByteBuf input) throws IOException { + if (inputCodec != null) { + int len = input.readableBytes(); + byte[] bytes = new byte[len]; + input.readBytes(bytes); + return inputCodec.decode(bytes); + } + return null; + } + + @Override + public byte[] outputEncode(Object output) throws IOException { + if (outputCodec != null) { + return outputCodec.encode(output); + } + return null; + } + + @Override + public void outputWriteToStream(Object output, CodedOutputStream stream) throws IOException { + if (outputCodec != null) { + outputCodec.writeTo(output, stream); + } + } + + @Override + public int getInputSerializedSize(Object input) throws IOException { + if (inputCodec != null) { + return inputCodec.size(input); + } + return 0; + } + + @Override + public int getOutputSerializedSize(Object output) throws IOException { + if (outputCodec != null) { + return outputCodec.size(output); + } + return 0; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/ProtobufRpcMethodInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/ProtobufRpcMethodInfo.java new file mode 100644 index 00000000..3f1ee027 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/ProtobufRpcMethodInfo.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.Message; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.utils.ProtobufUtils; +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; + +@Setter +@Getter +public class ProtobufRpcMethodInfo extends RpcMethodInfo { + private Message inputInstance; + private Method inputParseFromMethod; + private Method inputGetDefaultInstanceMethod; + + private Message outputInstance; + private Method outputParseFromMethod; + private Method outputGetDefaultInstanceMethod; + + public ProtobufRpcMethodInfo(Method method) { + super(method); + try { + this.inputGetDefaultInstanceMethod = ((Class) inputClasses[0]).getMethod("getDefaultInstance"); + this.inputInstance = (Message) inputGetDefaultInstanceMethod.invoke(null); + this.inputParseFromMethod = ((Class) inputClasses[0]).getMethod("parseFrom", byte[].class); + + this.outputGetDefaultInstanceMethod = ((Class) outputClass).getMethod("getDefaultInstance"); + this.outputInstance = (Message) outputGetDefaultInstanceMethod.invoke(null); + this.outputParseFromMethod = ((Class) outputClass).getMethod("parseFrom", byte[].class); + + } catch (Exception ex) { + throw new IllegalArgumentException(ex); + } + } + + @Override + public byte[] inputEncode(Object input) throws IOException { + if (input instanceof Message) { + return ((Message) input).toByteArray(); + } + return null; + } + + @Override + public void inputWriteToStream(Object input, CodedOutputStream stream) throws IOException { + if (input instanceof Message) { + ((Message) input).writeTo(stream); + stream.flush(); + } + } + + @Override + public Object outputDecode(byte[] output) throws IOException { + if (outputParseFromMethod != null && output != null) { + try { + return outputParseFromMethod.invoke(outputClass, output); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + return null; + } + + @Override + public Object outputDecode(ByteBuf output) throws IOException { + return ProtobufUtils.parseFrom(output, outputInstance); + } + + @Override + public Object outputDecode(DynamicCompositeByteBuf output) throws IOException { + return ProtobufUtils.parseFrom(output, outputInstance); + } + + public Object outputDecode(InputStream stream) throws IOException { + if (outputGetDefaultInstanceMethod != null && stream != null) { + try { + Message proto = (Message) outputGetDefaultInstanceMethod.invoke(null); + proto = proto.newBuilderForType().mergeFrom(stream).build(); + return proto; + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + return null; + } + + public Object inputDecode(byte[] input) throws IOException { + return inputInstance.getParserForType().parseFrom(input); + } + + public Object inputDecode(byte[] input, int offset, int len) throws IOException { + return inputInstance.getParserForType().parseFrom(input, offset, len); + } + + public Object inputDecode(ByteBuf input) throws IOException { + return ProtobufUtils.parseFrom(input, inputInstance); + } + + public Object inputDecode(DynamicCompositeByteBuf input) throws IOException { + return ProtobufUtils.parseFrom(input, inputInstance); + } + + public Object inputDecode(InputStream stream) throws IOException { + if (inputGetDefaultInstanceMethod != null && stream != null) { + try { + Message proto = (Message) inputGetDefaultInstanceMethod.invoke(null); + proto = proto.newBuilderForType().mergeFrom(stream).build(); + return proto; + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + return null; + } + + public byte[] outputEncode(Object output) throws IOException { + if (output instanceof Message) { + return ((Message) output).toByteArray(); + } + return null; + } + + @Override + public void outputWriteToStream(Object output, CodedOutputStream stream) throws IOException { + if (output instanceof Message) { + ((Message) output).writeTo(stream); + stream.flush(); + } + } + + @Override + public int getInputSerializedSize(Object input) throws IOException { + if (input instanceof Message) { + return ((Message) input).getSerializedSize(); + } + return 0; + } + + @Override + public int getOutputSerializedSize(Object output) throws IOException { + if (output instanceof Message) { + return ((Message) output).getSerializedSize(); + } + return 0; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/RpcContext.java b/brpc-java-core/src/main/java/com/baidu/brpc/RpcContext.java new file mode 100644 index 00000000..14b16f0c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/RpcContext.java @@ -0,0 +1,129 @@ +package com.baidu.brpc; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Map; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.util.concurrent.FastThreadLocal; +import lombok.Getter; +import lombok.Setter; + +/** + * runtime information which are not in Request/Response. + * it should be reset when begin new rpc. + * the requestBinaryAttachment should be released at server. + * the responseBinaryAttachment should be released at client. + */ +@Setter +@Getter +public class RpcContext { + private static final FastThreadLocal CURRENT_RPC_CONTEXT = new FastThreadLocal() { + @Override + protected RpcContext initialValue() { + return new RpcContext(); + } + }; + + public static boolean isSet() { + return CURRENT_RPC_CONTEXT.isSet(); + } + + public static RpcContext getContext() { + return CURRENT_RPC_CONTEXT.get(); + } + + public static void removeContext() { + CURRENT_RPC_CONTEXT.remove(); + } + + private Integer readTimeoutMillis; + + private Integer writeTimeoutMillis; + + /** + * logId of protocol, application can set it. + */ + private Integer logId; + + /** + * set custom service instance tag, + * so that load balance can select instance with the tag. + */ + private String serviceTag; + + private Map requestKvAttachment; + private ByteBuf requestBinaryAttachment; + + private Map responseKvAttachment; + private ByteBuf responseBinaryAttachment; + + private Channel channel; + + private SocketAddress remoteAddress; + + public void reset() { + readTimeoutMillis = null; + writeTimeoutMillis = null; + logId = null; + requestKvAttachment = null; + requestBinaryAttachment = null; + responseBinaryAttachment = null; + responseKvAttachment = null; + channel = null; + remoteAddress = null; + serviceTag = null; + } + + public void setRequestBinaryAttachment(ByteBuf byteBuf) { + this.requestBinaryAttachment = byteBuf == null ? null : Unpooled.wrappedBuffer(byteBuf); + } + + public void setRequestBinaryAttachment(byte[] bytes) { + this.requestBinaryAttachment = bytes == null ? null : Unpooled.wrappedBuffer(bytes); + } + + public void setRequestKvAttachment(String key, Object value) { + if (requestKvAttachment == null) { + requestKvAttachment = new HashMap(); + } + requestKvAttachment.put(key, value); + } + + public void setRequestKvAttachment(Map attachment) { + if (requestKvAttachment == null) { + requestKvAttachment = attachment; + } else { + requestKvAttachment.putAll(attachment); + } + } + + public void setResponseKvAttachment(String key, Object value) { + if (responseKvAttachment == null) { + responseKvAttachment = new HashMap(); + } + responseKvAttachment.put(key, value); + } + + public void setResponseKvAttachment(Map attachment) { + if (responseKvAttachment == null) { + responseKvAttachment = attachment; + } else { + responseKvAttachment.putAll(attachment); + } + } + + public String getRemoteHost() { + if (remoteAddress != null) { + InetSocketAddress remoteAddress = (InetSocketAddress) this.remoteAddress; + InetAddress address = remoteAddress.getAddress(); + return address.getHostAddress(); + } else { + return null; + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/RpcMethodInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/RpcMethodInfo.java new file mode 100644 index 00000000..b49fd990 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/RpcMethodInfo.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.protocol.nshead.NSHeadMeta; +import com.baidu.brpc.utils.RpcMetaUtils; +import com.baidu.brpc.utils.ThreadPool; +import com.google.protobuf.CodedOutputStream; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * rpc method info is parsed when application initialized. + * it can be both used at client and server side. + */ +@Setter +@Getter +public class RpcMethodInfo { + protected Method method; + protected String serviceName; + protected String methodName; + protected Type[] inputClasses; + protected Type outputClass; + protected NSHeadMeta nsHeadMeta; + // instance of interface which method belongs to + protected Object target; + protected ThreadPool threadPool; + + public RpcMethodInfo(Method method) { + RpcMetaUtils.RpcMetaInfo metaInfo = RpcMetaUtils.parseRpcMeta(method); + this.serviceName = metaInfo.getServiceName(); + this.methodName = metaInfo.getMethodName(); + this.method = method; + Type[] inputClasses = method.getGenericParameterTypes(); + if (inputClasses.length < 0) { + throw new IllegalArgumentException("invalid params"); + } + this.inputClasses = inputClasses; + this.outputClass = method.getGenericReturnType(); + this.nsHeadMeta = method.getAnnotation(NSHeadMeta.class); + } + + /** + * encode request at client inside + * + * @param input the input + * @return the byte[] + * @throws IOException Signals that an I/O exception has occurred. + */ + public byte[] inputEncode(Object input) throws IOException { + return null; + } + + /** + * encode request at client inside + * @param input request + * @param stream out buffer stream + * @throws IOException io exception + */ + public void inputWriteToStream(Object input, CodedOutputStream stream) throws IOException { + } + + /** + * decode response at client side + * + * @param output response byte array + * @return response proto object + * @throws IOException Signals that an I/O exception has occurred. + */ + public Object outputDecode(byte[] output) throws IOException { + return null; + } + + /** + * decode response at client side + * @param output response netty ByteBuf + * @return response proto object + * @throws IOException + */ + public Object outputDecode(ByteBuf output) throws IOException { + return null; + } + + public Object outputDecode(DynamicCompositeByteBuf output) throws IOException { + return null; + } + + /** + * decode request at server side + * @param input request byte array + * @return request proto instance + * @throws IOException + */ + public Object inputDecode(byte[] input) throws IOException { + return null; + } + + /** + * decode request at server side + * @param input request netty {@link ByteBuf} + * @return request proto instance + * @throws IOException + */ + public Object inputDecode(ByteBuf input) throws IOException { + return null; + } + + public Object inputDecode(DynamicCompositeByteBuf input) throws IOException { + return null; + } + + /** + * encode response proto instance at server side + * @param output response proto instance + * @return encoded byte array + * @throws IOException + */ + public byte[] outputEncode(Object output) throws IOException { + return null; + } + + /** + * encode response to stream at server side + * @param output response object + * @param stream output stream + * @throws IOException + */ + public void outputWriteToStream(Object output, CodedOutputStream stream) throws IOException { + } + + /** + * get serialized size of request proto instance + * @param input proto instance + * @return serialized size + * @throws IOException + */ + public int getInputSerializedSize(Object input) throws IOException { + return 0; + } + + /** + * get serialized size of response proto instance + * @param output response object + * @return serialized size + * @throws IOException + */ + public int getOutputSerializedSize(Object output) throws IOException { + return 0; + } +} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/buffer/DynamicCompositeByteBuf.java b/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBuf.java similarity index 75% rename from starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/buffer/DynamicCompositeByteBuf.java rename to brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBuf.java index 2b415152..dba852e6 100644 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/buffer/DynamicCompositeByteBuf.java +++ b/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBuf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,26 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.baidu.cloud.starlight.api.transport.buffer; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.CompositeByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.buffer.UnpooledByteBufAllocator; +package com.baidu.brpc.buffer; import java.nio.ByteOrder; import java.util.ArrayDeque; import java.util.Iterator; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.CompositeByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.buffer.UnpooledByteBufAllocator; + /** - * Migrate from brpc-java, see https://github.com/baidu/brpc-java/blob/master/docs/cn/composite_buffer.md Dynamic - * composite multi {@link ByteBuf}, and it can be read just like a normal {@link ByteBuf}. Be constructed by one or many - * readable {@link ByteBuf}, reference count of these buffers is not retained, and are managed by - * {@link DynamicCompositeByteBuf}. When dynamic composite byte buffer release, it will release every sub buffers. When - * the readable size of a sub buffer is zero, it will be removed from dynamic composite byte buffer, and will be - * release. Currently, DynamicCompositeByteBuf does not support to write bytes, because netty {@link ByteBuf} has - * satisfied already. DynamicCompositeByteBuf is used to handle network sticking / unpacking, and can achieve zero copy. + * dynamically composite multi {@link ByteBuf}, and it can be read just like a normal {@link ByteBuf}. + * it can be constructed by one or many readable {@link ByteBuf}, + * reference count of these buffers is not retained, and are managed by {@link DynamicCompositeByteBuf}. + * when dynamic composite byte buffer release, it will release every sub buffers. + * when the readable size of a sub buffer is zero, it will be removed from dynamic composite byte buffer, + * and will be release. + * Currently, DynamicCompositeByteBuf does not support to write bytes, + * because netty {@link ByteBuf} has satisfied already. */ public class DynamicCompositeByteBuf { private ArrayDeque buffers; @@ -50,7 +51,6 @@ public DynamicCompositeByteBuf(int capacity) { /** * construct a new {@link DynamicCompositeByteBuf} with netty {@link ByteBuf}. - * * @param buf input buf, readable size should be greater than zero. */ public DynamicCompositeByteBuf(ByteBuf buf) { @@ -61,7 +61,6 @@ public DynamicCompositeByteBuf(ByteBuf buf) { /** * construct a new {@link DynamicCompositeByteBuf} with netty {@link ByteBuf} array. - * * @param bufs byte buffer array, readable size of each element should be greater than zero. * @param offset offset at array * @param len length for create the new {@link DynamicCompositeByteBuf} @@ -92,7 +91,6 @@ public boolean hasArray() { /** * it not check hasArray for performance - * * @return the backing array if it exists. {@code null} otherwise. */ public byte[] array() throws UnsupportedOperationException { @@ -104,8 +102,8 @@ public byte[] array() throws UnsupportedOperationException { /** * it not check hasArray for performance - * - * @return The offset within this buffer's array of the first element of the buffer + * @return The offset within this buffer's array of the first element + * of the buffer */ public int arrayOffset() throws UnsupportedOperationException { if (hasArray()) { @@ -126,9 +124,8 @@ public boolean isReadable() { } /** - * convert {@link DynamicCompositeByteBuf} to netty {@link ByteBuf}, the reference count of its underlying buffers - * are not increased. - * + * convert {@link DynamicCompositeByteBuf} to netty {@link ByteBuf}, + * the reference count of its underlying buffers are not increased. * @return netty ByteBuf */ public ByteBuf nettyByteBuf() { @@ -139,13 +136,13 @@ public ByteBuf nettyByteBuf() { if (size == 1) { return buffers.pop(); } - return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, size, buffers.toArray(new ByteBuf[0])); + return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, + size, buffers.toArray(new ByteBuf[0])); } /** - * add netty {@link ByteBuf} to {@link DynamicCompositeByteBuf}. the reference count of netty byte buffer will be - * managed by {@link DynamicCompositeByteBuf}. - * + * add netty {@link ByteBuf} to {@link DynamicCompositeByteBuf}. + * the reference count of netty byte buffer will be managed by {@link DynamicCompositeByteBuf}. * @param buffer netty byte buffer */ public void addBuffer(ByteBuf buffer) { @@ -159,14 +156,16 @@ public void addBuffer(ByteBuf buffer) { } /** - * Returns a new {@link CompositeByteBuf} which slice the first {@code length} of this composite byte buffer and - * increases the {@code readerIndex} by the size of the new slice (= {@code length}). + * Returns a new {@link CompositeByteBuf} which slice the first {@code length} of this + * composite byte buffer and increases the {@code readerIndex} by the size + * of the new slice (= {@code length}). * * @param length the size of the new composite byte buffer * * @return the newly created composite byte buffer * - * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes} + * @throws IndexOutOfBoundsException + * if {@code length} is greater than {@code this.readableBytes} */ public ByteBuf readRetainedSlice(int length) { if (length > readableBytes) { @@ -228,15 +227,16 @@ public ByteBuf readRetainedSlice(int length) { } /** - * Returns a new {@link CompositeByteBuf} which slice the first {@code length} of this composite byte buffer while - * they maintain separate indexes and marks. This method does not modify {@code readerIndex} or {@code writerIndex} - * of this buffer. + * Returns a new {@link CompositeByteBuf} which slice the first {@code length} of this + * composite byte buffer while they maintain separate indexes and marks. + * This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @param length the size of the new composite byte buffer * * @return the newly created composite byte buffer * - * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes} + * @throws IndexOutOfBoundsException + * if {@code length} is greater than {@code this.readableBytes} */ public ByteBuf retainedSlice(int length) { if (length > readableBytes) { @@ -317,21 +317,24 @@ public DynamicCompositeByteBuf readBytes(byte[] dst) { } /** - * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} and - * increases the {@code readerIndex} by the number of the transferred bytes (= {@code length}). + * Transfers this buffer's data to the specified destination starting at + * the current {@code readerIndex} and increases the {@code readerIndex} + * by the number of the transferred bytes (= {@code length}). * * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer + * @param length the number of bytes to transfer * - * @throws IndexOutOfBoundsException if the specified {@code dstIndex} is less than {@code 0}, if {@code length} is - * greater than {@code this.readableBytes}, or if {@code dstIndex + length} is greater than - * {@code dst.length} + * @throws IndexOutOfBoundsException + * if the specified {@code dstIndex} is less than {@code 0}, + * if {@code length} is greater than {@code this.readableBytes}, or + * if {@code dstIndex + length} is greater than {@code dst.length} */ public DynamicCompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { if (dst == null) { throw new NullPointerException(); } - if (dstIndex < 0 || dstIndex >= dst.length || dstIndex + length > dst.length || dstIndex + length < 0) { + if (dstIndex < 0 || dstIndex >= dst.length + || dstIndex + length > dst.length || dstIndex + length < 0) { throw new IndexOutOfBoundsException(); } @@ -354,9 +357,11 @@ public DynamicCompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { } /** - * Gets a byte at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 1} in this buffer. + * Gets a byte at the current {@code readerIndex} and increases + * the {@code readerIndex} by {@code 1} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 1} */ public byte readByte() { checkReadableBytes0(1); @@ -370,20 +375,22 @@ public byte readByte() { } /** - * Gets an unsigned byte at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 1} in - * this buffer. + * Gets an unsigned byte at the current {@code readerIndex} and increases + * the {@code readerIndex} by {@code 1} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 1} */ public short readUnsignedByte() { return (short) (readByte() & 0xFF); } /** - * Gets a 16-bit short integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 2} - * in this buffer. + * Gets a 16-bit short integer at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 2} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 2} */ public short readShort() { checkReadableBytes0(2); @@ -405,10 +412,12 @@ public short readShort() { } /** - * Gets a 16-bit short integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the - * {@code readerIndex} by {@code 2} in this buffer. + * Gets a 16-bit short integer at the current {@code readerIndex} + * in the Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 2} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 2} */ public short readShortLE() { checkReadableBytes0(2); @@ -429,30 +438,34 @@ public short readShortLE() { } /** - * Gets an unsigned 16-bit short integer at the current {@code readerIndex} and increases the {@code readerIndex} by - * {@code 2} in this buffer. + * Gets an unsigned 16-bit short integer at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 2} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 2} */ public int readUnsignedShort() { return readShort() & 0xFFFF; } /** - * Gets an unsigned 16-bit short integer at the current {@code readerIndex} in the Little Endian Byte Order and - * increases the {@code readerIndex} by {@code 2} in this buffer. + * Gets an unsigned 16-bit short integer at the current {@code readerIndex} + * in the Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 2} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 2} */ public int readUnsignedShortLE() { return readShortLE() & 0xFFFF; } /** - * Gets a 32-bit integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 4} in - * this buffer. + * Gets a 32-bit integer at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 4} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 4} */ public int readInt() { checkReadableBytes0(4); @@ -473,10 +486,12 @@ public int readInt() { } /** - * Gets a 32-bit integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the - * {@code readerIndex} by {@code 4} in this buffer. + * Gets a 32-bit integer at the current {@code readerIndex} + * in the Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 4} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 4} */ public int readIntLE() { checkReadableBytes0(4); @@ -497,10 +512,11 @@ public int readIntLE() { } /** - * Gets a 64-bit integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 8} in - * this buffer. + * Gets a 64-bit integer at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 8} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 8} */ public long readLong() { checkReadableBytes0(8); @@ -521,10 +537,12 @@ public long readLong() { } /** - * Gets a 64-bit integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the - * {@code readerIndex} by {@code 8} in this buffer. + * Gets a 64-bit integer at the current {@code readerIndex} + * in the Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 8} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 8} */ public long readLongLE() { checkReadableBytes0(8); @@ -545,50 +563,57 @@ public long readLongLE() { } /** - * Gets a 2-byte UTF-16 character at the current {@code readerIndex} and increases the {@code readerIndex} by - * {@code 2} in this buffer. + * Gets a 2-byte UTF-16 character at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 2} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 2} */ public char readChar() { return (char) readShort(); } /** - * Gets a 32-bit floating point number at the current {@code readerIndex} and increases the {@code readerIndex} by - * {@code 4} in this buffer. + * Gets a 32-bit floating point number at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 4} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 4} */ public float readFloat() { return Float.intBitsToFloat(readInt()); } /** - * Gets a 32-bit floating point number at the current {@code readerIndex} in Little Endian Byte Order and increases - * the {@code readerIndex} by {@code 4} in this buffer. + * Gets a 32-bit floating point number at the current {@code readerIndex} + * in Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 4} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 4} */ public float readFloatLE() { return Float.intBitsToFloat(readIntLE()); } /** - * Gets a 64-bit floating point number at the current {@code readerIndex} and increases the {@code readerIndex} by - * {@code 8} in this buffer. + * Gets a 64-bit floating point number at the current {@code readerIndex} + * and increases the {@code readerIndex} by {@code 8} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 8} */ public double readDouble() { return Double.longBitsToDouble(readLong()); } /** - * Gets a 64-bit floating point number at the current {@code readerIndex} in Little Endian Byte Order and increases - * the {@code readerIndex} by {@code 8} in this buffer. + * Gets a 64-bit floating point number at the current {@code readerIndex} + * in Little Endian Byte Order and increases the {@code readerIndex} + * by {@code 8} in this buffer. * - * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} + * @throws IndexOutOfBoundsException + * if {@code this.readableBytes} is less than {@code 8} */ public double readDoubleLE() { return Double.longBitsToDouble(readLongLE()); @@ -600,8 +625,9 @@ public ByteOrder order() { private void checkReadableBytes0(int length) { if (readableBytes < length) { - throw new IndexOutOfBoundsException( - String.format("length(%d) exceeds readableBytes(%d): %s", length, readableBytes, this)); + throw new IndexOutOfBoundsException(String.format( + "length(%d) exceeds readableBytes(%d): %s", + length, readableBytes, this)); } } @@ -626,6 +652,7 @@ public void release() { } } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -642,4 +669,4 @@ public String toString() { return sb.toString(); } -} \ No newline at end of file +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStream.java b/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStream.java new file mode 100644 index 00000000..26fb47f9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStream.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.buffer; + +import java.io.InputStream; +import java.io.IOException; +import java.io.EOFException; +import java.io.DataInput; +import java.io.DataInputStream; + +/** + * An {@link InputStream} which reads data from a {@link DynamicCompositeByteBuf}. + *

+ * A read operation against this stream will occur at the {@code readerIndex} + * of its underlying buffer and the {@code readerIndex} will increase during + * the read operation. Please note that it only reads up to the number of + * readable bytes of its underlying buffer. + *

+ * This stream implements {@link DataInput} for your convenience. + * + */ +public class DynamicCompositeByteBufInputStream extends InputStream implements DataInput { + private DynamicCompositeByteBuf buffer; + private boolean closed; + private boolean releaseOnClose; + + /** + * Creates a new stream which reads data from the specified {@code buffer} + * @param compositeByteBuf The buffer which provides the content for this {@link InputStream}. + */ + public DynamicCompositeByteBufInputStream(DynamicCompositeByteBuf compositeByteBuf) { + this(compositeByteBuf, false); + } + + /** + * Creates a new stream which reads data from the specified {@code buffer} + * @param buffer The buffer which provides the content for this {@link InputStream}. + * @param releaseOnClose {@code true} means that when {@link #close()} is called + * then {@link DynamicCompositeByteBuf#release()} + * will be called on {@code buffer}. + */ + public DynamicCompositeByteBufInputStream(DynamicCompositeByteBuf buffer, boolean releaseOnClose) { + if (buffer == null) { + throw new NullPointerException("buffer"); + } + + this.releaseOnClose = releaseOnClose; + this.buffer = buffer; + } + + @Override + public void close() throws IOException { + try { + super.close(); + } finally { + // The Closable interface says "If the stream is already closed then invoking this method has no effect." + if (releaseOnClose && !closed) { + closed = true; + buffer.release(); + } + } + } + + @Override + public int available() throws IOException { + return buffer.readableBytes(); + } + + @Override + public boolean markSupported() { + return false; + } + + @Override + public int read() throws IOException { + if (!buffer.isReadable()) { + return -1; + } + return buffer.readByte() & 0xff; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int available = available(); + if (available == 0) { + return -1; + } + + len = Math.min(available, len); + buffer.readBytes(b, off, len); + return len; + } + + @Override + public long skip(long n) throws IOException { + if (n > Integer.MAX_VALUE) { + return skipBytes(Integer.MAX_VALUE); + } else { + return skipBytes((int) n); + } + } + + public int skipBytes(int n) throws IOException { + int nBytes = Math.min(available(), n); + buffer.skipBytes(nBytes); + return nBytes; + } + + @Override + public boolean readBoolean() throws IOException { + checkAvailable(1); + return read() != 0; + } + + @Override + public byte readByte() throws IOException { + if (!buffer.isReadable()) { + throw new EOFException(); + } + return buffer.readByte(); + } + + @Override + public char readChar() throws IOException { + return (char) readShort(); + } + + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(readLong()); + } + + @Override + public float readFloat() throws IOException { + return Float.intBitsToFloat(readInt()); + } + + @Override + public void readFully(byte[] b) throws IOException { + readFully(b, 0, b.length); + } + + @Override + public void readFully(byte[] b, int off, int len) throws IOException { + checkAvailable(len); + buffer.readBytes(b, off, len); + } + + @Override + public int readInt() throws IOException { + checkAvailable(4); + return buffer.readInt(); + } + + private final StringBuilder lineBuf = new StringBuilder(); + + @Override + public String readLine() throws IOException { + lineBuf.setLength(0); + + loop: + while (true) { + if (!buffer.isReadable()) { + return lineBuf.length() > 0 ? lineBuf.toString() : null; + } + + int c = buffer.readUnsignedByte(); + switch (c) { + case '\n': + break loop; + + case '\r': + if (buffer.isReadable() && (char) buffer.readUnsignedByte() == '\n') { + buffer.skipBytes(1); + } + break loop; + + default: + lineBuf.append((char) c); + } + } + + return lineBuf.toString(); + } + + @Override + public long readLong() throws IOException { + checkAvailable(8); + return buffer.readLong(); + } + + @Override + public short readShort() throws IOException { + checkAvailable(2); + return buffer.readShort(); + } + + @Override + public String readUTF() throws IOException { + return DataInputStream.readUTF(this); + } + + @Override + public int readUnsignedByte() throws IOException { + return readByte() & 0xff; + } + + @Override + public int readUnsignedShort() throws IOException { + return readShort() & 0xffff; + } + + private void checkAvailable(int fieldSize) throws IOException { + if (fieldSize < 0) { + throw new IndexOutOfBoundsException("fieldSize cannot be a negative number"); + } + if (fieldSize > available()) { + throw new EOFException("fieldSize is too long! Length is " + fieldSize + + ", but maximum is " + available()); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/AsyncAwareFuture.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/AsyncAwareFuture.java new file mode 100644 index 00000000..e1cbdca6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/AsyncAwareFuture.java @@ -0,0 +1,10 @@ +package com.baidu.brpc.client; + +import java.util.concurrent.Future; + +/** + * Created by wanghongfei on 2019-04-19. + */ +public interface AsyncAwareFuture extends Future { + boolean isAsync(); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/BrpcProxy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/BrpcProxy.java new file mode 100644 index 00000000..aa50ebcb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/BrpcProxy.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; + +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.DefaultInterceptorChain; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.nshead.NSHeadMeta; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.utils.ProtobufUtils; + +import lombok.extern.slf4j.Slf4j; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * Created by huwenwei on 2017/4/25. + */ +@SuppressWarnings("unchecked") +@Slf4j +public class BrpcProxy implements MethodInterceptor { + + private static final Set notProxyMethodSet = new HashSet(); + + static { + notProxyMethodSet.add("getClass"); + notProxyMethodSet.add("hashCode"); + notProxyMethodSet.add("equals"); + notProxyMethodSet.add("clone"); + notProxyMethodSet.add("toString"); + notProxyMethodSet.add("notify"); + notProxyMethodSet.add("notifyAll"); + notProxyMethodSet.add("wait"); + notProxyMethodSet.add("finalize"); + } + + private RpcClient rpcClient; + + private Map rpcMethodMap = new HashMap(); + + /** + * 初始化时提前解析好method信息,在rpc交互时会更快。 + * + * @param rpcClient rpc client对象 + * @param clazz rpc接口类 + */ + protected BrpcProxy(RpcClient rpcClient, Class clazz) { + this.rpcClient = rpcClient; + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + if (notProxyMethodSet.contains(method.getName())) { + log.debug("{}:{} does not need to proxy", + method.getDeclaringClass().getName(), method.getName()); + continue; + } + + Class[] parameterTypes = method.getParameterTypes(); + int paramLength = parameterTypes.length; + if (paramLength >= 1 + && Future.class.isAssignableFrom(method.getReturnType()) + && !RpcCallback.class.isAssignableFrom(parameterTypes[paramLength - 1])) { + throw new IllegalArgumentException("returnType is Future, but last argument is not RpcCallback"); + } + + Method syncMethod = method; + if (paramLength > 1) { + int startIndex = 0; + int endIndex = paramLength - 1; + // has callback, async rpc + if (RpcCallback.class.isAssignableFrom(parameterTypes[paramLength - 1])) { + endIndex--; + paramLength--; + } + Class[] actualParameterTypes = new Class[paramLength]; + for (int i = 0; startIndex <= endIndex; i++) { + actualParameterTypes[i] = parameterTypes[startIndex++]; + } + try { + syncMethod = method.getDeclaringClass().getMethod( + method.getName(), actualParameterTypes); + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException("can not find sync method:" + method.getName()); + } + } + + RpcMethodInfo methodInfo; + ProtobufUtils.MessageType messageType = ProtobufUtils.getMessageType(syncMethod); + if (messageType == ProtobufUtils.MessageType.PROTOBUF) { + methodInfo = new ProtobufRpcMethodInfo(syncMethod); + } else if (messageType == ProtobufUtils.MessageType.JPROTOBUF) { + methodInfo = new JprotobufRpcMethodInfo(syncMethod); + } else { + methodInfo = new RpcMethodInfo(syncMethod); + } + + rpcMethodMap.put(method.getName(), methodInfo); + log.debug("client serviceName={}, methodName={}", + method.getDeclaringClass().getName(), method.getName()); + } + } + + public static T getProxy(RpcClient rpcClient, Class clazz) { + return getProxy(rpcClient, clazz, null); + } + + public static T getProxy(RpcClient rpcClient, Class clazz, NamingOptions namingOptions) { + rpcClient.setServiceInterface(clazz, namingOptions); + rpcClient.getLoadBalanceInterceptor().setRpcClient(rpcClient); + rpcClient.getInterceptors().add(rpcClient.getLoadBalanceInterceptor()); + Enhancer en = new Enhancer(); + en.setSuperclass(clazz); + en.setCallback(new BrpcProxy(rpcClient, clazz)); + return (T) en.create(); + } + + /** + * 调用用户接口时候, 实际执行的方法 + * + * @param obj + * @param method + * @param args + * @param proxy + * + * @return + * + * @throws Throwable + */ + @Override + public Object intercept(Object obj, Method method, Object[] args, + MethodProxy proxy) throws Throwable { + String methodName = method.getName(); + RpcMethodInfo rpcMethodInfo = rpcMethodMap.get(methodName); + if (rpcMethodInfo == null) { + log.debug("{}:{} does not need to proxy", + method.getDeclaringClass().getName(), methodName); + return proxy.invokeSuper(obj, args); + } + Request request = null; + Response response = null; + + List interceptors = null; + int readTimeout = 10 * 1000; + int writeTimeout = 10 * 1000; + + interceptors = rpcClient.getInterceptors(); + request = rpcClient.getProtocol().createRequest(); + response = rpcClient.getProtocol().getResponse(); + if (rpcClient.getProtocol() instanceof ServerPushProtocol) { + SPHead spHead = ((ServerPushProtocol) rpcClient.getProtocol()).createSPHead(); + spHead.setType(SPHead.TYPE_REQUEST); + request.setSpHead(spHead); + } + + request.setCompressType(rpcClient.getRpcClientOptions().getCompressType().getNumber()); + request.setSubscribeInfo(rpcClient.getSubscribeInfo()); + readTimeout = rpcClient.getRpcClientOptions().getReadTimeoutMillis(); + writeTimeout = rpcClient.getRpcClientOptions().getWriteTimeoutMillis(); + + try { + + request.setTarget(obj); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + NSHeadMeta nsHeadMeta = rpcMethodInfo.getNsHeadMeta(); + NSHead nsHead = nsHeadMeta == null ? new NSHead() : new NSHead(0, nsHeadMeta.id(), nsHeadMeta.version(), + nsHeadMeta.provider(), 0); + request.setNsHead(nsHead); + + // parse request params + RpcCallback callback = null; + int argLength = args.length; + if (argLength > 1) { + int startIndex = 0; + int endIndex = argLength - 1; + // 异步调用 + if (args[endIndex] instanceof RpcCallback) { + callback = (RpcCallback) args[endIndex]; + endIndex -= 1; + argLength -= 1; + } + + if (argLength <= 0) { + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, "invalid params"); + } + + Object[] sendArgs = new Object[argLength]; + for (int i = 0; startIndex <= endIndex; i++) { + sendArgs[i] = args[startIndex++]; + } + request.setArgs(sendArgs); + request.setCallback(callback); + } else { + // sync call + request.setArgs(args); + } + + if (RpcContext.isSet()) { + RpcContext rpcContext = RpcContext.getContext(); + // attachment + if (rpcContext.getRequestKvAttachment() != null) { + request.setKvAttachment(rpcContext.getRequestKvAttachment()); + } + if (rpcContext.getRequestBinaryAttachment() != null) { + request.setBinaryAttachment(rpcContext.getRequestBinaryAttachment()); + } + if (rpcContext.getLogId() != null) { + request.getNsHead().logId = rpcContext.getLogId(); + request.setLogId(rpcContext.getLogId()); + } + if (rpcContext.getServiceTag() != null) { + request.setServiceTag(rpcContext.getServiceTag()); + } + if (rpcContext.getReadTimeoutMillis() != null) { + request.setReadTimeoutMillis(rpcContext.getReadTimeoutMillis()); + } + if (rpcContext.getWriteTimeoutMillis() != null) { + request.setWriteTimeoutMillis(rpcContext.getWriteTimeoutMillis()); + } + rpcContext.reset(); + } + + if (request.getReadTimeoutMillis() == null) { + request.setReadTimeoutMillis(readTimeout); + } + if (request.getWriteTimeoutMillis() == null) { + request.setWriteTimeoutMillis(writeTimeout); + } + + InterceptorChain interceptorChain = new DefaultInterceptorChain(interceptors); + try { + interceptorChain.intercept(request, response); + if (response.getException() != null) { + throw new RpcException(response.getException()); + } + if (request.getCallback() != null) { + return response.getRpcFuture(); + } else { + return response.getResult(); + } + } catch (Exception ex) { + log.error("exception :", ex); + throw new RpcException(response.getException()); + } + } finally { + if (request != null) { + // release send buffer because we retain send buffer when send request. + request.release(); + } + } + } + + public Map getRpcMethodMap() { + return rpcMethodMap; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/FastFutureStore.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/FastFutureStore.java new file mode 100644 index 00000000..291e7bd6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/FastFutureStore.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReferenceArray; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A lock-free datastructure faster than #{@link java.util.concurrent.ConcurrentHashMap} in certain circumstance. + * When the underlying array runs out of space, FastFutureStore will downgrade to #{@link ConcurrentHashMap} + *

+ * Created by wanghongfei on 2018/11/19. + */ +public class FastFutureStore { + private static final Logger LOG = LoggerFactory.getLogger(FastFutureStore.class); + + /** + * Default capacity of the internal array + */ + private static final int DEFAULT_ARRAY_CAP = 10000; + + private static volatile FastFutureStore singletonInstance; + + /** + * Atomic array used to store #{@link RpcFuture} + */ + private AtomicReferenceArray futArray; + + /** + * A counter used to calculate array index + */ + private AtomicLong slotCounter = new AtomicLong(0); + + /** + * Capacity of the internal array + */ + private int cap; + + /** + * Downgrade to ConcurrentHashMap when array is exhausted + */ + private Map backupMap = new ConcurrentHashMap(); + + /** + * The boundary between array-stored id and map-stored id. + * Binary format: 0100 0000 0000 0000 ... ... 0000(64 bits). + *

+ * Ids less than(01xx xxxx ... xxx) this value should be stored in array. + * Ids greater than(01xx xxxx ... xxx) this value should be stored in map. + */ + private static long COUNTER_VALUE_BOUNDARY = (long) 0x1 << 62; + + /** + * @param cap capacity of the internal array + */ + public FastFutureStore(int cap) { + if (cap < 1) { + cap = DEFAULT_ARRAY_CAP; + } + + this.cap = cap; + this.futArray = new AtomicReferenceArray(cap); + } + + /** + * Obtain singleton object + * + * @param cap Capacity of the internal array + * + * @return The singleton instance. + */ + public static FastFutureStore getInstance(int cap) { + if (null == singletonInstance) { + synchronized(FastFutureStore.class) { + if (null == singletonInstance) { + singletonInstance = new FastFutureStore(cap); + } + } + } + + return singletonInstance; + } + + /** + * Add an object. + * + * @return Identifier of the added object + */ + public long put(RpcFuture fut) { + int loopCount = 0; + + // loop until finding an empty slot + while (true) { + long currentCounter = slotCounter.getAndIncrement(); + + if (currentCounter >= COUNTER_VALUE_BOUNDARY) { + slotCounter.getAndSet(0); + continue; + } + + int slot = mapSlot(currentCounter); + + // try to put object into current slot + boolean success = futArray.compareAndSet(slot, null, fut); + if (success) { + fut.setCorrelationId(currentCounter); + return currentCounter; + } + + // loopCount is bigger than capacity indicating FastFutureStore has ran out of space + if (++loopCount >= cap) { + LOG.debug("FutureStore exhausted, current=%d, store id in map", cap); + return storeInMap(currentCounter, fut); + } + } + } + + /** + * Retrieve object identified by id + * + * @param id Identifier returned by #{@link #put(RpcFuture)} + */ + public RpcFuture get(long id) { + if (isStoredInMap(id)) { + return getFromMap(id); + } + + return getFromArray(id); + } + + /** + * Retrieve and remove object identified by id + * + * @param id Identifier returned by #{@link #put(RpcFuture)} + * + * @return null if nothing found + */ + public RpcFuture getAndRemove(long id) { + if (isStoredInMap(id)) { + return getAndRemoveMap(id); + } + + return getAndRemoveArray(id); + } + + /** + * Return the count of the objects. + */ + public int size() { + int sum = 0; + for (int ix = 0; ix < cap; ++ix) { + if (null != futArray.get(ix)) { + ++sum; + } + } + + return sum + backupMap.size(); + } + + /** + * Traverse and invoke #{@link StoreWalker} on every element. + * + * @param walker Define the action needed to be performed for elements + */ + public void traverse(StoreWalker walker) { + if (null == walker) { + throw new NullPointerException("walker cannot be null"); + } + + // do not traverse if no elements inside + if (!hasElements()) { + return; + } + + // traverse array + for (int ix = 0; ix < cap; ++ix) { + RpcFuture fut = futArray.get(ix); + if (null == fut) { + // skip empty slot + continue; + } + + boolean keep = walker.visitElement(fut); + if (!keep) { + // delete element + futArray.set(ix, null); + // invoke hook action + walker.actionAfterDelete(fut); + } + } + + // traverse map + for (Map.Entry pair : backupMap.entrySet()) { + boolean keep = walker.visitElement(pair.getValue()); + if (!keep) { + backupMap.remove(pair.getKey()); + walker.actionAfterDelete(pair.getValue()); + } + } + } + + private RpcFuture getAndRemoveMap(long id) { + return backupMap.remove(id); + } + + private RpcFuture getAndRemoveArray(long id) { + int slot = mapSlot(id); + if (!rangeCheck(slot)) { + return null; + } + + // get the old value + RpcFuture prev = futArray.get(slot); + // remove only when RpcFuture.logId is equal with current id + if (null != prev && prev.getCorrelationId() == id) { + futArray.set(slot, null); + return prev; + } + + return null; + + } + + private RpcFuture getFromMap(long id) { + return backupMap.get(id); + } + + private RpcFuture getFromArray(long id) { + int slot = mapSlot(id); + if (!rangeCheck(slot)) { + return null; + } + + return futArray.get(slot); + } + + private long storeInMap(long id, RpcFuture fut) { + long mapId = markMapBit(id); + backupMap.put(mapId, fut); + + return mapId; + } + + private long markMapBit(long id) { + return id | COUNTER_VALUE_BOUNDARY; + } + + private boolean isStoredInMap(long id) { + return id >= COUNTER_VALUE_BOUNDARY; + } + + private boolean hasElements() { + boolean arrayNotEmpty = false; + for (int ix = 0; ix < cap; ++ix) { + if (null != futArray.get(ix)) { + arrayNotEmpty = true; + break; + } + } + + boolean mapNotEmpty = !backupMap.isEmpty(); + + return arrayNotEmpty || mapNotEmpty; + } + + private int mapSlot(long id) { + return (int) (id % cap); + } + + private boolean rangeCheck(int index) { + return index < cap && index >= 0; + } + + public interface StoreWalker { + /** + * Action on a none-null element. + * + * @param fut The current element, may not be null + * + * @return Indicate whether this element should be deleted. False: delete, True: reserve + */ + boolean visitElement(RpcFuture fut); + + /** + * Action performed after a deletion of the element. + * + * @param fut The deleted object. + */ + void actionAfterDelete(RpcFuture fut); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/MethodUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/MethodUtils.java new file mode 100644 index 00000000..b37b83ee --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/MethodUtils.java @@ -0,0 +1,65 @@ +package com.baidu.brpc.client; + +import java.lang.reflect.Method; +import java.util.concurrent.Future; + +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.utils.ProtobufUtils; + +public class MethodUtils { + + public static RpcMethodInfo getRpcMethodInfo(Class clazz, String methodName) { + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + if (!method.getName().equals(methodName)) { + continue; + } + Class[] parameterTypes = method.getParameterTypes(); + int paramLength = parameterTypes.length; + if (paramLength < 1) { + throw new IllegalArgumentException( + "invalid params, the correct is ([RpcContext], Request, [Callback])"); + } + if (Future.class.isAssignableFrom(method.getReturnType()) + && (paramLength < 1 || !RpcCallback.class.isAssignableFrom(parameterTypes[paramLength - 1]))) { + throw new IllegalArgumentException("returnType is Future, but last argument is not RpcCallback"); + } + + Method syncMethod = method; + if (paramLength > 1) { + int startIndex = 0; + int endIndex = paramLength - 1; + // has callback, async rpc + if (RpcCallback.class.isAssignableFrom(parameterTypes[paramLength - 1])) { + endIndex--; + paramLength--; + } + Class[] actualParameterTypes = new Class[paramLength]; + for (int i = 0; startIndex <= endIndex; i++) { + actualParameterTypes[i] = parameterTypes[startIndex++]; + } + try { + syncMethod = method.getDeclaringClass().getMethod( + method.getName(), actualParameterTypes); + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException("can not find sync method:" + method.getName()); + } + } + + RpcMethodInfo methodInfo; + ProtobufUtils.MessageType messageType = ProtobufUtils.getMessageType(syncMethod); + if (messageType == ProtobufUtils.MessageType.PROTOBUF) { + methodInfo = new ProtobufRpcMethodInfo(syncMethod); + } else if (messageType == ProtobufUtils.MessageType.JPROTOBUF) { + methodInfo = new JprotobufRpcMethodInfo(syncMethod); + } else { + methodInfo = new RpcMethodInfo(syncMethod); + } + + return methodInfo; + } + return null; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcCallback.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcCallback.java new file mode 100644 index 00000000..2b73a97c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcCallback.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +public interface RpcCallback { + + void success(T response); + + void fail(Throwable e); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClient.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClient.java new file mode 100644 index 00000000..a4592d4a --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClient.java @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.handler.IdleChannelHandler; +import com.baidu.brpc.client.handler.RpcClientHandler; +import com.baidu.brpc.client.instance.BasicInstanceProcessor; +import com.baidu.brpc.client.instance.Endpoint; +import com.baidu.brpc.client.instance.EnhancedInstanceProcessor; +import com.baidu.brpc.client.instance.InstanceProcessor; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.client.loadbalance.LoadBalanceManager; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.client.loadbalance.RandomStrategy; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.ClientTraceInterceptor; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.interceptor.LoadBalanceInterceptor; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.ListNamingService; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.naming.NamingServiceFactoryManager; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolManager; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.spi.ExtensionLoaderManager; +import com.baidu.brpc.thread.BrpcIoThreadPoolInstance; +import com.baidu.brpc.thread.BrpcWorkClientThreadPoolInstance; +import com.baidu.brpc.thread.ClientCallBackThreadPoolInstance; +import com.baidu.brpc.thread.ClientTimeoutTimerInstance; +import com.baidu.brpc.thread.ShutDownManager; +import com.baidu.brpc.utils.BrpcConstants; +import com.baidu.brpc.utils.CustomThreadFactory; +import com.baidu.brpc.utils.ThreadPool; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollChannelOption; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollMode; +import io.netty.channel.epoll.EpollSocketChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import lombok.Getter; +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.channels.ClosedChannelException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Created by huwenwei on 2017/4/25. + */ +@SuppressWarnings("unchecked") +@Getter +public class RpcClient { + private static final Logger LOG = LoggerFactory.getLogger(RpcClient.class); + + private RpcClientOptions rpcClientOptions = new RpcClientOptions(); + private Bootstrap bootstrap; + private Timer timeoutTimer; + private Protocol protocol; + private LoadBalanceStrategy loadBalanceStrategy; + private List interceptors = new ArrayList(); + private LoadBalanceInterceptor loadBalanceInterceptor = new LoadBalanceInterceptor(); + private NamingService namingService; + private ThreadPool workThreadPool; + private EventLoopGroup ioThreadPool; + private Class serviceInterface; + private SubscribeInfo subscribeInfo; + private AtomicBoolean stop = new AtomicBoolean(false); + private InstanceProcessor instanceProcessor; + + /** + * callBack thread when method invoke fail + */ + private ExecutorService callbackThread; + + /** + * 保存单例的引用 + */ + private FastFutureStore fastFutureStore; + + public RpcClient(String namingServiceUrl) { + this(namingServiceUrl, new RpcClientOptions(), null); + } + + public RpcClient(String namingServiceUrl, RpcClientOptions options) { + this(namingServiceUrl, options, null); + } + + /** + * parse naming service url, connect to servers + * + * @param serviceUrl format like "list://127.0.0.1:8200" + * @param options rpc client options + */ + public RpcClient(String serviceUrl, + final RpcClientOptions options, + List interceptors) { + Validate.notEmpty(serviceUrl); + Validate.notNull(options); + + ExtensionLoaderManager.getInstance().loadAllExtensions(options.getEncoding()); + // parse naming + BrpcURL url = new BrpcURL(serviceUrl); + NamingServiceFactory namingServiceFactory + = NamingServiceFactoryManager.getInstance().getNamingServiceFactory(url.getSchema()); + this.namingService = namingServiceFactory.createNamingService(url); + boolean singleServer = false; + if (namingService instanceof ListNamingService) { + List instances = namingService.lookup(null); + singleServer = instances.size() == 1; + } + + this.init(options, interceptors, singleServer); + } + + public RpcClient(Endpoint endPoint) { + this(endPoint, null); + } + + public RpcClient(Endpoint endPoint, RpcClientOptions options) { + this(endPoint, options, null); + } + + public RpcClient(Endpoint endPoint, RpcClientOptions options, List interceptors) { + if (null == options) { + options = new RpcClientOptions(); + } + ExtensionLoaderManager.getInstance().loadAllExtensions(options.getEncoding()); + this.init(options, interceptors, true); + instanceProcessor.addInstance(new ServiceInstance(endPoint)); + } + + public RpcClient(List endPoints) { + this(endPoints, new RpcClientOptions(), null); + } + + public RpcClient(List endPoints, RpcClientOptions options, List interceptors) { + ExtensionLoaderManager.getInstance().loadAllExtensions(options.getEncoding()); + this.init(options, interceptors, endPoints.size() == 1); + for (Endpoint endpoint : endPoints) { + instanceProcessor.addInstance(new ServiceInstance(endpoint)); + } + } + + public static T getProxy(RpcClient rpcClient, Class clazz, NamingOptions namingOptions) { + return BrpcProxy.getProxy(rpcClient, clazz, namingOptions); + } + + public static T getProxy(RpcClient rpcClient, Class clazz) { + return BrpcProxy.getProxy(rpcClient, clazz, null); + } + + /** + * @param service + */ + public void registerPushService(Object service) { + ServiceManager.getInstance().registerPushService(service); + + // 如果只注册了pushService,没有注册一个普通的服务的话, 报错 + if (instanceProcessor.getInstances().size() == 0) { + LOG.error("there should be have normal services before register push service."); + throw new RpcException("there should be have normal services before register push service"); + } + } + + public T getProxy(Class clazz, NamingOptions namingOptions) { + return BrpcProxy.getProxy(this, clazz, namingOptions); + } + + public T getProxy(Class clazz) { + return BrpcProxy.getProxy(this, clazz, null); + } + + public void setServiceInterface(Class clazz) { + setServiceInterface(clazz, null); + } + + public void setServiceInterface(Class clazz, NamingOptions namingOptions) { + if (this.serviceInterface != null) { + throw new RpcException("serviceInterface must not be set repeatedly, please use another RpcClient"); + } + if (clazz.getInterfaces().length == 0) { + this.serviceInterface = clazz; + } else { + // if it is async interface, we should subscribe the sync interface + this.serviceInterface = clazz.getInterfaces()[0]; + } + + if (namingService != null) { + if (namingOptions != null) { + subscribeInfo = new SubscribeInfo(namingOptions); + } else { + subscribeInfo = new SubscribeInfo(); + } + subscribeInfo.setInterfaceName(serviceInterface.getName()); + List instances = this.namingService.lookup(subscribeInfo); + instanceProcessor.addInstances(instances); + this.namingService.subscribe(subscribeInfo, new NotifyListener() { + @Override + public void notify(Collection addList, + Collection deleteList) { + instanceProcessor.addInstances(addList); + instanceProcessor.deleteInstances(deleteList); + } + }); + } + } + + public void shutdown() { + stop(); + } + + public void stop() { + // avoid stop multi times + if (stop.compareAndSet(false, true)) { + if (namingService != null) { + namingService.unsubscribe(subscribeInfo); + } + if (instanceProcessor != null) { + instanceProcessor.stop(); + } + if (loadBalanceStrategy != null) { + loadBalanceStrategy.destroy(); + } + if (ioThreadPool != null && !rpcClientOptions.isGlobalThreadPoolSharing()) { + ioThreadPool.shutdownGracefully().syncUninterruptibly(); + } + if (workThreadPool != null && !rpcClientOptions.isGlobalThreadPoolSharing()) { + workThreadPool.stop(); + } + } + } + + public boolean isShutdown() { + return stop.get(); + } + + /** + * select instance by load balance and select channel from the instance. + * when user call this function explicitly, he should return the channel to avoid connection leak. + * + * @return netty channel + */ + public Channel selectChannel(Request request) { + BrpcChannel brpcChannel = loadBalanceStrategy.selectInstance( + request, + instanceProcessor.getHealthyInstanceChannels(), + request.getSelectedInstances()); + if (brpcChannel == null) { + LOG.debug("no available healthy server, so random select one unhealthy server"); + RandomStrategy randomStrategy = new RandomStrategy(); + randomStrategy.init(this); + brpcChannel = randomStrategy.selectInstance( + request, + instanceProcessor.getUnHealthyInstanceChannels(), + request.getSelectedInstances()); + if (brpcChannel == null) { + throw new RpcException(RpcException.NETWORK_EXCEPTION, "no available instance"); + } + } + Channel channel; + try { + channel = brpcChannel.getChannel(); + } catch (NoSuchElementException full) { + int maxConnections = brpcChannel.getCurrentMaxConnection() * 2; + brpcChannel.updateMaxConnection(maxConnections); + String errMsg = String.format("channel pool is exhausted, and double maxTotalConnection,server=%s:%d", + brpcChannel.getServiceInstance().getIp(), brpcChannel.getServiceInstance().getPort()); + LOG.debug(errMsg); + throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg, full); + } catch (IllegalStateException illegalState) { + String errMsg = String.format("channel pool is closed, server=%s:%d", + brpcChannel.getServiceInstance().getIp(), brpcChannel.getServiceInstance().getPort()); + LOG.debug(errMsg); + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg, illegalState); + } catch (Exception connectedFailed) { + String errMsg; + if (rpcClientOptions.getChannelType() == ChannelType.POOLED_CONNECTION) { + errMsg = String.format("channel pool make new object failed, " + + "active=%d,idle=%d,server=%s:%d, ex=%s", + brpcChannel.getActiveConnectionNum(), + brpcChannel.getIdleConnectionNum(), + brpcChannel.getServiceInstance().getIp(), + brpcChannel.getServiceInstance().getPort(), + connectedFailed.getMessage()); + } else { + errMsg = String.format("get channel failed, ex=%s", connectedFailed.getMessage()); + } + LOG.debug(errMsg); + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg, connectedFailed); + } + + if (channel == null) { + String errMsg = "channel is null, retry another channel"; + LOG.debug(errMsg); + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg); + } + if (!channel.isActive()) { + brpcChannel.incFailedNum(); + // 如果连接不是有效的,从连接池中剔除。 + brpcChannel.removeChannel(channel); + String errMsg = "channel is non active, retry another channel"; + throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg); + } + return channel; + } + + /** + * select channel from endpoint which is selected by custom load balance. + * + * @param endpoint ip:port + * @return netty channel + */ + public Channel selectChannel(Endpoint endpoint) { + BrpcChannel brpcChannel = instanceProcessor.getInstanceChannelMap().get(endpoint); + if (brpcChannel == null) { + LOG.warn("instance:{} not found, may be it is removed from naming service.", endpoint); + throw new RpcException(RpcException.SERVICE_EXCEPTION, "instance not found:" + endpoint); + } + Channel channel; + try { + channel = brpcChannel.getChannel(); + } catch (Exception ex) { + throw new RpcException(RpcException.NETWORK_EXCEPTION, "select channel failed from " + endpoint, ex); + } + if (!channel.isActive()) { + brpcChannel.incFailedNum(); + // 如果连接不是有效的,从连接池中剔除。 + brpcChannel.removeChannel(channel); + String errMsg = "channel is non active, retry another channel"; + throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg); + } + return channel; + } + + public void returnChannel(Channel channel) { + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(channel); + channelInfo.getChannelGroup().returnChannel(channel); + } + + public void removeChannel(Channel channel) { + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(channel); + channelInfo.getChannelGroup().removeChannel(channel); + } + + public AsyncAwareFuture sendRequest(Request request) { + // select instance by load balance, and select channel from instance. + Channel channel = selectChannel(request); + request.setChannel(channel); + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(request.getChannel()); + BrpcChannel brpcChannel = channelInfo.getChannelGroup(); + protocol.beforeRequestSent(request, this, brpcChannel); + + // encode request + RpcFuture rpcFuture = RpcFuture.createRpcFuture(request, this); + channelInfo.setCorrelationId(rpcFuture.getCorrelationId()); + rpcFuture.setChannelInfo(channelInfo); + request.setRpcFuture(rpcFuture); + request.setCorrelationId(rpcFuture.getCorrelationId()); + try { + request.setSendBuf(protocol.encodeRequest(request)); + } catch (Throwable t) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, t.getMessage(), t); + } + + // register timeout timer + RpcTimeoutTimer timeoutTask = new RpcTimeoutTimer(channelInfo, request.getCorrelationId(), this); + Timeout timeout = timeoutTimer.newTimeout(timeoutTask, request.getReadTimeoutMillis(), TimeUnit.MILLISECONDS); + request.getRpcFuture().setTimeout(timeout); + try { + // netty will release the send buffer after sent. + // we retain here, so it can be used when rpc retry. + request.retain(); + ChannelFuture sendFuture = request.getChannel().writeAndFlush(request.getSendBuf()); + sendFuture.awaitUninterruptibly(request.getWriteTimeoutMillis()); + if (!sendFuture.isSuccess()) { + if (!(sendFuture.cause() instanceof ClosedChannelException)) { + LOG.warn("send request failed, channelActive={}, ex=", + request.getChannel().isActive(), sendFuture.cause()); + } + String errMsg = String.format("send request failed, channelActive=%b", + request.getChannel().isActive()); + throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg); + } + } catch (Exception ex) { + channelInfo.handleRequestFail(rpcClientOptions.getChannelType(), request.getCorrelationId()); + timeout.cancel(); + if (ex instanceof RpcException) { + throw (RpcException) ex; + } else { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex.getMessage(), ex); + } + } + + // return channel + channelInfo.handleRequestSuccess(rpcClientOptions.getChannelType()); + return request.getRpcFuture(); + } + + public void triggerCallback(Runnable runnable) { + if (!callbackThread.isTerminated()) { + callbackThread.execute(runnable); + } + } + + private void init(final RpcClientOptions options, List interceptors, boolean singleServer) { + Validate.notNull(options); + try { + this.rpcClientOptions.copyFrom(options); + } catch (Exception ex) { + LOG.warn("init rpc options failed, so use default"); + } + if (interceptors != null) { + this.interceptors.addAll(interceptors); + } + this.interceptors.add(new ClientTraceInterceptor()); + this.protocol = ProtocolManager.getInstance().getProtocol(options.getProtocolType()); + if (!protocol.returnChannelBeforeResponse() + && rpcClientOptions.getChannelType() == ChannelType.SINGLE_CONNECTION) { + String errorString = "it can't use SINGLE_CONNECTION when protocol returns channel before response"; + LOG.error(errorString); + throw new IllegalArgumentException(errorString); + } + fastFutureStore = FastFutureStore.getInstance(options.getFutureBufferSize()); + timeoutTimer = ClientTimeoutTimerInstance.getOrCreateInstance(); + + // singleServer do not need healthChecker + if (singleServer) { + instanceProcessor = new BasicInstanceProcessor(this); + } else { + instanceProcessor = new EnhancedInstanceProcessor(this); + } + + // 负载均衡算法 + loadBalanceStrategy = LoadBalanceManager.getInstance().createLoadBalance( + rpcClientOptions.getLoadBalanceType()); + loadBalanceStrategy.init(this); + + // init once + ShutDownManager.getInstance(); + boolean threadPoolSharing = rpcClientOptions.isGlobalThreadPoolSharing(); + if (threadPoolSharing) { + this.workThreadPool = + BrpcWorkClientThreadPoolInstance.getOrCreateInstance(rpcClientOptions.getWorkThreadNum()); + if (rpcClientOptions.getIoEventType() == BrpcConstants.IO_EVENT_NETTY_EPOLL) { + ioThreadPool = BrpcIoThreadPoolInstance.getOrCreateEpollInstance(options.getIoThreadNum()); + } else { + ioThreadPool = BrpcIoThreadPoolInstance.getOrCreateNioInstance(options.getIoThreadNum()); + } + } else { + this.workThreadPool = new ThreadPool(rpcClientOptions.getWorkThreadNum(), + new CustomThreadFactory("client-work-thread")); + if (rpcClientOptions.getIoEventType() == BrpcConstants.IO_EVENT_NETTY_EPOLL) { + ioThreadPool = new EpollEventLoopGroup(options.getIoThreadNum(), + new CustomThreadFactory("client-io-thread")); + } else { + ioThreadPool = new NioEventLoopGroup(options.getIoThreadNum(), + new CustomThreadFactory("client-io-thread")); + } + } + + this.callbackThread = ClientCallBackThreadPoolInstance.getOrCreateInstance(1); + + // init netty bootstrap + bootstrap = new Bootstrap(); + if (rpcClientOptions.getIoEventType() == BrpcConstants.IO_EVENT_NETTY_EPOLL) { + bootstrap.channel(EpollSocketChannel.class); + bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); + } else { + bootstrap.channel(NioSocketChannel.class); + } + + bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, rpcClientOptions.getConnectTimeoutMillis()); + bootstrap.option(ChannelOption.SO_KEEPALIVE, rpcClientOptions.isKeepAlive()); + bootstrap.option(ChannelOption.SO_REUSEADDR, rpcClientOptions.isReuseAddr()); + bootstrap.option(ChannelOption.TCP_NODELAY, rpcClientOptions.isTcpNoDelay()); + bootstrap.option(ChannelOption.SO_RCVBUF, rpcClientOptions.getReceiveBufferSize()); + bootstrap.option(ChannelOption.SO_SNDBUF, rpcClientOptions.getSendBufferSize()); + final RpcClientHandler rpcClientHandler = new RpcClientHandler(RpcClient.this); + final ChannelInitializer initializer = new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + if (rpcClientOptions.getChannelType() == ChannelType.SINGLE_CONNECTION) { + ch.pipeline().addLast(new IdleStateHandler(0, 0, rpcClientOptions.getKeepAliveTime())); + ch.pipeline().addLast(new IdleChannelHandler()); + } + ch.pipeline().addLast(rpcClientHandler); + } + }; + + bootstrap.group(ioThreadPool).handler(initializer); + } + + public void removeLogId(long id) { + fastFutureStore.getAndRemove(id); + } + + public RpcClientOptions getRpcClientOptions() { + return rpcClientOptions; + } + + public Protocol getProtocol() { + return protocol; + } + + public CopyOnWriteArrayList getHealthyInstances() { + return instanceProcessor.getHealthyInstanceChannels(); + } + + public List getInterceptors() { + return interceptors; + } + + public Bootstrap getBootstrap() { + return bootstrap; + } + + public ThreadPool getWorkThreadPool() { + return workThreadPool; + } + + public LoadBalanceStrategy getLoadBalanceStrategy() { + return loadBalanceStrategy; + } + + public boolean isLongConnection() { + return rpcClientOptions.getChannelType() != ChannelType.SHORT_CONNECTION; + } + + public NamingService getNamingService() { + return namingService; + } + + public Timer getTimeoutTimer() { + return timeoutTimer; + } + + public LoadBalanceInterceptor getLoadBalanceInterceptor() { + return loadBalanceInterceptor; + } + + public void setLoadBalanceInterceptor(LoadBalanceInterceptor loadBalanceInterceptor) { + this.loadBalanceInterceptor = loadBalanceInterceptor; + } + + public SubscribeInfo getSubscribeInfo() { + return subscribeInfo; + } + + public InstanceProcessor getInstanceProcessor() { + return instanceProcessor; + } + + public void setInstanceProcessor(InstanceProcessor instanceProcessor) { + this.instanceProcessor = instanceProcessor; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClientOptions.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClientOptions.java new file mode 100644 index 00000000..58774f18 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcClientOptions.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.utils.BrpcConstants; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * Created by wenweihu86 on 2017/4/24. + */ +@Setter +@Getter +@NoArgsConstructor +public class RpcClientOptions { + + private int protocolType = Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE; + private int connectTimeoutMillis = 1000; + private int readTimeoutMillis = 1000; + private int writeTimeoutMillis = 1000; + private int maxTotalConnections = 8; + private int minIdleConnections = 8; + private int maxTryTimes = 3; + // Maximum time for connection idle, testWhileIdle needs to be true + private long timeBetweenEvictionRunsMillis = 5 * 60 * 1000; + private int loadBalanceType = LoadBalanceStrategy.LOAD_BALANCE_FAIR; + // for fair load balance strategy only + private int latencyWindowSizeOfFairLoadBalance = 30; + // for fair load balance strategy only + // the ratio of activeInstancesNum/totalInstancesNum in brpc client, if this ratio not reached, + // fair load balance will not start, just use random load balance strategy + private float activeInstancesRatioOfFairLoadBalance = 0.5f; + private int healthyCheckIntervalMillis = 3000; + // The keep alive + private boolean keepAlive = true; + private boolean reuseAddr = true; + private boolean tcpNoDelay = true; + // so linger + private int soLinger = 5; + // backlog + private int backlog = 100; + // receive buffer size + private int receiveBufferSize = 1024 * 64; + // send buffer size + private int sendBufferSize = 1024 * 64; + // keep alive time in seconds + private int keepAliveTime = 60 * 5; + // io threads, default use Netty default value + private int ioThreadNum = Runtime.getRuntime().availableProcessors(); + // threads used for deserialize rpc response and execute the callback + private int workThreadNum = Runtime.getRuntime().availableProcessors(); + /** + * io event type, netty or jdk + */ + private int ioEventType = BrpcConstants.IO_EVENT_JDK; + // FastFutureStore's max size + private int futureBufferSize = 1000000; + private String encoding = "utf-8"; + private Options.CompressType compressType = Options.CompressType.COMPRESS_TYPE_NONE; + private ChannelType channelType = ChannelType.POOLED_CONNECTION; + private String clientName; + + // share worker thread poll and event thread pool between multi RpcClients + private boolean globalThreadPoolSharing = false; + + public RpcClientOptions(RpcClientOptions options) { + this.copyFrom(options); + } + + public void copyFrom(RpcClientOptions another) { + this.activeInstancesRatioOfFairLoadBalance = another.activeInstancesRatioOfFairLoadBalance; + this.backlog = another.backlog; + this.channelType = another.channelType; + this.compressType = another.compressType; + this.connectTimeoutMillis = another.connectTimeoutMillis; + this.encoding = another.encoding; + this.futureBufferSize = another.futureBufferSize; + this.healthyCheckIntervalMillis = another.healthyCheckIntervalMillis; + this.ioThreadNum = another.ioThreadNum; + this.keepAlive = another.keepAlive; + this.keepAliveTime = another.keepAliveTime; + this.latencyWindowSizeOfFairLoadBalance = another.latencyWindowSizeOfFairLoadBalance; + this.loadBalanceType = another.loadBalanceType; + this.maxTotalConnections = another.maxTotalConnections; + this.maxTryTimes = another.maxTryTimes; + this.minIdleConnections = another.minIdleConnections; + this.protocolType = another.protocolType; + this.readTimeoutMillis = another.readTimeoutMillis; + this.receiveBufferSize = another.receiveBufferSize; + this.reuseAddr = another.reuseAddr; + this.sendBufferSize = another.sendBufferSize; + this.soLinger = another.soLinger; + this.tcpNoDelay = another.tcpNoDelay; + this.timeBetweenEvictionRunsMillis = another.timeBetweenEvictionRunsMillis; + this.workThreadNum = another.workThreadNum; + this.writeTimeoutMillis = another.writeTimeoutMillis; + this.clientName = another.clientName; + this.globalThreadPoolSharing = another.globalThreadPoolSharing; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcFuture.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcFuture.java new file mode 100644 index 00000000..cf7fb945 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcFuture.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ + +package com.baidu.brpc.client; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import com.baidu.brpc.protocol.Request; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.utils.CollectionUtils; + +import io.netty.util.Timeout; +import lombok.Getter; +import lombok.Setter; + +@SuppressWarnings("unchecked") +@Setter +@Getter +public class RpcFuture implements AsyncAwareFuture { + private static final Logger LOG = LoggerFactory.getLogger(RpcFuture.class); + + protected CountDownLatch latch; + protected Timeout timeout; + + protected RpcCallback callback; // callback cannot be set after init + protected ChannelInfo channelInfo; + protected RpcClient rpcClient; + protected RpcMethodInfo rpcMethodInfo; + + protected Response response; + protected boolean isDone; + // record the time of request + // used in FAIR load balancing + protected long startTime; + protected long endTime; + + protected volatile long correlationId; + + public RpcFuture() { + this.latch = new CountDownLatch(1); + this.startTime = System.currentTimeMillis(); + } + + public RpcFuture(long correlationId) { + this.correlationId = correlationId; + this.latch = new CountDownLatch(1); + this.startTime = System.currentTimeMillis(); + } + + public RpcFuture(Timeout timeout, + RpcMethodInfo rpcMethodInfo, + RpcCallback callback, + ChannelInfo channelInfo, + RpcClient rpcClient) { + init(timeout, rpcMethodInfo, callback, channelInfo, rpcClient); + } + + public static RpcFuture createRpcFuture(Request request, RpcClient rpcClient) { + // create RpcFuture object + RpcFuture rpcFuture = new RpcFuture(); + rpcFuture.setRpcMethodInfo(request.getRpcMethodInfo()); + rpcFuture.setCallback(request.getCallback()); + rpcFuture.setRpcClient(rpcClient); + // generate correlationId + FastFutureStore.getInstance(0).put(rpcFuture); + return rpcFuture; + } + + public void init(Timeout timeout, + RpcMethodInfo rpcMethodInfo, + RpcCallback callback, + ChannelInfo channelInfo, + RpcClient rpcClient) { + this.timeout = timeout; + this.rpcMethodInfo = rpcMethodInfo; + this.callback = callback; + this.channelInfo = channelInfo; + this.latch = new CountDownLatch(1); + this.startTime = System.currentTimeMillis(); + this.rpcClient = rpcClient; + } + + public void handleConnection(Response response) { + this.response = response; + this.endTime = System.currentTimeMillis(); + + // only long connection need to update channel group + if (rpcClient.isLongConnection()) { + if (response != null && response.getResult() != null) { + channelInfo.getChannelGroup().updateLatency((int) (endTime - startTime)); + channelInfo.handleResponseSuccess(); + } else { + channelInfo.getChannelGroup().updateLatencyWithReadTimeOut(); + channelInfo.handleResponseFail(); + } + } else { + channelInfo.close(); + } + + timeout.cancel(); + latch.countDown(); + isDone = true; + } + + public void handleResponse(Response response) { + handleConnection(response); + // invoke the chain of interceptors when async scene + if (isAsync() && CollectionUtils.isNotEmpty(rpcClient.getInterceptors())) { + int length = rpcClient.getInterceptors().size(); + for (int i = length - 1; i >= 0; i--) { + rpcClient.getInterceptors().get(i).handleResponse(response); + } + } + + if (isAsync()) { + setRpcContext(); + if (response == null) { + callback.fail(new RpcException(RpcException.SERVICE_EXCEPTION, "internal error")); + } else if (response.getResult() != null) { + callback.success((T) response.getResult()); + } else { + callback.fail(response.getException()); + } + } + } + + @Override + public boolean isAsync() { + return callback != null; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return isDone; + } + + @Override + public T get() throws InterruptedException { + latch.await(); + if (response != null && response.getException() != null) { + throw new RpcException(response.getException()); + } + if (response == null) { + throw new RpcException(RpcException.TIMEOUT_EXCEPTION); + } + setRpcContext(); + return (T) response.getResult(); + } + + @Override + public T get(long timeout, TimeUnit unit) { + try { + boolean ret = latch.await(timeout, unit); + if (!ret) { + throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "timeout"); + } + assert response != null; + if (response.getException() != null) { + throw new RpcException(response.getException()); + } + setRpcContext(); + return (T) response.getResult(); + } catch (InterruptedException e) { + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, e); + } + } + + @Override + public String toString() { + return super.toString() + "@correlationId = " + correlationId; + } + + protected void setRpcContext() { + if (response == null) { + return; + } + if (response.getBinaryAttachment() != null + || response.getKvAttachment() != null) { + RpcContext rpcContext = RpcContext.getContext(); + if (response.getBinaryAttachment() != null) { + rpcContext.setResponseBinaryAttachment(response.getBinaryAttachment()); + } + if (response.getKvAttachment() != null) { + rpcContext.setResponseKvAttachment(response.getKvAttachment()); + } + } + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcTimeoutTimer.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcTimeoutTimer.java new file mode 100644 index 00000000..b47497bb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/RpcTimeoutTimer.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ +package com.baidu.brpc.client; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.server.RpcServer; + +import io.netty.util.Timeout; +import io.netty.util.TimerTask; + +/** + * Created by wanghongfei on 2019-04-18. + */ +public class RpcTimeoutTimer implements TimerTask { + private static final Logger LOG = LoggerFactory.getLogger(RpcTimeoutTimer.class); + + private ChannelInfo channelInfo; + private long correlationId; + private RpcClient rpcClient; + private RpcServer rpcServer; + + public RpcTimeoutTimer( + ChannelInfo channelInfo, + long correlationId, + RpcClient rpcClient) { + this.channelInfo = channelInfo; + this.correlationId = correlationId; + this.rpcClient = rpcClient; + } + + public RpcTimeoutTimer( + ChannelInfo channelInfo, + long correlationId, + RpcServer rpcServer) { + this.channelInfo = channelInfo; + this.correlationId = correlationId; + this.rpcServer = rpcServer; + } + + @Override + public void run(Timeout timeout) { + RpcFuture future = channelInfo.removeRpcFuture(correlationId); + if (future != null) { + String ip = future.getChannelInfo().getChannelGroup().getServiceInstance().getIp(); + int port = future.getChannelInfo().getChannelGroup().getServiceInstance().getPort(); + long elapseTime = System.currentTimeMillis() - future.getStartTime(); + String errMsg = String.format("request timeout,correlationId=%d,ip=%s,port=%d,elapse=%dms", + correlationId, ip, port, elapseTime); + LOG.info(errMsg); + Response response = rpcClient != null ? rpcClient.getProtocol().createResponse() : + rpcServer.getProtocol().createResponse(); + response.setException(new RpcException(RpcException.TIMEOUT_EXCEPTION, errMsg)); + response.setRpcFuture(future); + future.handleResponse(response); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/AbstractBrpcChannel.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/AbstractBrpcChannel.java new file mode 100644 index 00000000..13b5ff36 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/AbstractBrpcChannel.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ +package com.baidu.brpc.client.channel; + +import java.net.InetSocketAddress; +import java.util.Queue; + +import com.baidu.brpc.server.push.RegisterService; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.FastFutureStore; +import com.baidu.brpc.client.MethodUtils; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushProtocol; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractBrpcChannel implements BrpcChannel { + protected ServiceInstance serviceInstance; + protected Bootstrap bootstrap; + protected Protocol protocol; + protected RpcClient rpcClient; + + public AbstractBrpcChannel(ServiceInstance serviceInstance, Bootstrap bootstrap, Protocol protocol, + RpcClient rpcClient) { + this.serviceInstance = serviceInstance; + this.bootstrap = bootstrap; + this.protocol = protocol; + this.rpcClient = rpcClient; + } + + @Override + public void updateChannel(Channel channel) { + } + + // server push 模式下, 把client的clientName发送到server去 + public void sendClientNameToServer(ChannelFuture channelFuture) { + RpcClientOptions rpcClientOptions = rpcClient.getRpcClientOptions(); + + RpcRequest r = new RpcRequest(); + r.setChannel(channelFuture.channel()); + r.setReadTimeoutMillis(10 * 1000); + r.setWriteTimeoutMillis(10 * 1000); + SPHead spHead = ((ServerPushProtocol) protocol).createSPHead(); + spHead.setType(SPHead.TYPE_REGISTER_REQUEST); // 注册类型 + r.setSpHead(spHead); + + String serviceName = RegisterService.class.getName(); + String methodName = "registerClient"; + r.setServiceName(serviceName); + r.setMethodName(methodName); + RpcMethodInfo rpcMethodInfo = MethodUtils.getRpcMethodInfo(RegisterService.class, methodName); + r.setRpcMethodInfo(rpcMethodInfo); + r.setArgs(new Object[] {rpcClient.getRpcClientOptions().getClientName()}); + + // generate correlationId + RpcFuture registerRpcFuture = new RpcFuture(); + long correlationId = FastFutureStore.getInstance(0).put(registerRpcFuture); + registerRpcFuture.setCorrelationId(correlationId); + // rpcFuture.setChannelInfo(channelInfo); + r.setCorrelationId(correlationId); + + ByteBuf byteBuf; + try { + log.debug("send sendClientNameToServer, name:{}, correlationId:{}", + rpcClientOptions.getClientName(), r.getCorrelationId()); + byteBuf = protocol.encodeRequest(r); + } catch (Exception e) { + log.error("send report packet to server, encode packet failed, msg:", e); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "rpc encode failed:", e); + } + channelFuture.channel().writeAndFlush(byteBuf); + } + + @Override + public Channel connect(final String ip, final int port) { + final ChannelFuture future = bootstrap.connect(new InetSocketAddress(ip, port)); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if (channelFuture.isSuccess()) { + log.debug("future callback, connect to {}:{} success, channel={}", + ip, port, channelFuture.channel()); + // 发送clientName包到server + if (protocol instanceof ServerPushProtocol) { + sendClientNameToServer(future); + } + } else { + log.debug("future callback, connect to {}:{} failed due to {}", + ip, port, channelFuture.cause().getMessage()); + } + } + }); + future.syncUninterruptibly(); + if (future.isSuccess()) { + return future.channel(); + } else { + // throw exception when connect failed to the connection pool acquirer + log.error("connect to {}:{} failed, msg={}", ip, port, future.cause().getMessage()); + throw new RpcException(future.cause()); + } + } + + @Override + public ServiceInstance getServiceInstance() { + return serviceInstance; + } + + @Override + public long getFailedNum() { + return 0; + } + + @Override + public void incFailedNum() { + } + + @Override + public Queue getLatencyWindow() { + return null; + } + + @Override + public void updateLatency(int latency) { + } + + @Override + public void updateLatencyWithReadTimeOut() { + } + + @Override + public Protocol getProtocol() { + return protocol; + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(serviceInstance.getIp()) + .append(serviceInstance.getPort()) + .toHashCode(); + } + + @Override + public boolean equals(Object object) { + boolean flag = false; + if (object != null && BrpcChannel.class.isAssignableFrom(object.getClass())) { + BrpcChannel rhs = (BrpcChannel) object; + flag = new EqualsBuilder() + .append(serviceInstance.getIp(), rhs.getServiceInstance().getIp()) + .append(serviceInstance.getPort(), rhs.getServiceInstance().getPort()) + .isEquals(); + } + return flag; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannel.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannel.java new file mode 100644 index 00000000..1d9f831b --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannel.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ + +package com.baidu.brpc.client.channel; + +import java.util.NoSuchElementException; +import java.util.Queue; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.protocol.Protocol; + +import io.netty.channel.Channel; + +public interface BrpcChannel { + Channel getChannel() throws Exception, NoSuchElementException, IllegalStateException; + + void returnChannel(Channel channel); + + void removeChannel(Channel channel); + + void updateChannel(Channel channel); + + void close(); + + Channel connect(final String ip, final int port); + + ServiceInstance getServiceInstance(); + + long getFailedNum(); + + void incFailedNum(); + + Queue getLatencyWindow(); + + void updateLatency(int latency); + + void updateLatencyWithReadTimeOut(); + + Protocol getProtocol(); + + void updateMaxConnection(int num); + + int getCurrentMaxConnection(); + + int getActiveConnectionNum(); + + int getIdleConnectionNum(); + + int hashCode(); + + boolean equals(Object object); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannelFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannelFactory.java new file mode 100644 index 00000000..2ba5e0ce --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcChannelFactory.java @@ -0,0 +1,19 @@ +package com.baidu.brpc.client.channel; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.instance.ServiceInstance; + +public class BrpcChannelFactory { + public static BrpcChannel createChannel(ServiceInstance instance, RpcClient rpcClient) { + ChannelType channelType = rpcClient.getRpcClientOptions().getChannelType(); + if (channelType == ChannelType.POOLED_CONNECTION) { + return new BrpcPooledChannel(instance, rpcClient); + } else if (channelType == ChannelType.SINGLE_CONNECTION) { + return new BrpcSingleChannel(instance, rpcClient); + } else if (channelType == ChannelType.SHORT_CONNECTION) { + return new BrpcShortChannel(instance, rpcClient); + } else { + throw new IllegalArgumentException("channel type is not valid:" + channelType.getName()); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcPooledChannel.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcPooledChannel.java new file mode 100644 index 00000000..41a39581 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcPooledChannel.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.channel; + +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.client.pool.ChannelPooledObjectFactory; + +import io.netty.channel.Channel; +import lombok.extern.slf4j.Slf4j; + +/** + * BrpcPooledChannelGroup class keeps fixed connections with one server + * Created by wenweihu86 on 2017/9/29. + */ + +@Slf4j +public class BrpcPooledChannel extends AbstractBrpcChannel { + private GenericObjectPool channelFuturePool; + /** + * failedNum only effect balanceStrategy + * thread-unsafe type can be accepted, so not use AtomicLong which may affect performance partly + */ + private volatile long failedNum; + private int readTimeOut; + private int latencyWindowSize; + /** + * Used to save the rpc latency of the recent several rpc calls. + * This is for the fair load balance algorithm. + */ + private Queue latencyWindow; + private RpcClientOptions rpcClientOptions; + + public BrpcPooledChannel(ServiceInstance serviceInstance, RpcClient rpcClient) { + super(serviceInstance, rpcClient.getBootstrap(), rpcClient.getProtocol(), rpcClient); + this.protocol = rpcClient.getProtocol(); + this.rpcClientOptions = rpcClient.getRpcClientOptions(); + this.readTimeOut = rpcClientOptions.getReadTimeoutMillis(); + this.latencyWindowSize = rpcClientOptions.getLatencyWindowSizeOfFairLoadBalance(); + this.latencyWindow = new ConcurrentLinkedQueue(); + GenericObjectPoolConfig conf = new GenericObjectPoolConfig(); + // Maximum waiting time, when you need to borrow a connection, the maximum waiting time, + // if the time is exceeded, throw an exception, -1 is no time limit + conf.setMaxWaitMillis(rpcClientOptions.getConnectTimeoutMillis()); + conf.setMaxTotal(rpcClientOptions.getMaxTotalConnections()); + conf.setMaxIdle(rpcClientOptions.getMaxTotalConnections()); + conf.setMinIdle(rpcClientOptions.getMinIdleConnections()); + // Connect test when idle, start asynchronous evict thread for failure detection + conf.setTestWhileIdle(true); + // Maximum time for connection idle, testWhileIdle needs to be true + conf.setTimeBetweenEvictionRunsMillis(rpcClientOptions.getTimeBetweenEvictionRunsMillis()); + channelFuturePool = new GenericObjectPool(new ChannelPooledObjectFactory( + this, serviceInstance.getIp(), serviceInstance.getPort()), conf); + try { + channelFuturePool.preparePool(); + } catch (Exception ex) { + log.warn("init min idle object pool failed"); + } + } + + @Override + public Channel getChannel() throws Exception, NoSuchElementException, IllegalStateException { + return channelFuturePool.borrowObject(); + } + + @Override + public void returnChannel(Channel channel) { + try { + channelFuturePool.returnObject(channel); + } catch (Exception e) { + log.debug("return channel failed:{}", e.getMessage()); + } + } + + @Override + public void removeChannel(Channel channel) { + try { + channelFuturePool.invalidateObject(channel); + } catch (Exception e) { + log.debug("remove channel failed:{}", e.getMessage()); + } + } + + @Override + public void close() { + channelFuturePool.close(); + } + + @Override + public long getFailedNum() { + return failedNum; + } + + @Override + public void incFailedNum() { + this.failedNum++; + } + + @Override + public Queue getLatencyWindow() { + return latencyWindow; + } + + @Override + public void updateLatency(int latency) { + latencyWindow.add(latency); + if (latencyWindow.size() > latencyWindowSize) { + latencyWindow.poll(); + } + } + + + @Override + public void updateMaxConnection(int num) { + + channelFuturePool.setMaxTotal(num); + channelFuturePool.setMaxIdle(num); + + } + + @Override + public int getCurrentMaxConnection() { + return channelFuturePool.getMaxTotal(); + } + + @Override + public int getActiveConnectionNum() { + return channelFuturePool.getNumActive(); + } + + @Override + public int getIdleConnectionNum() { + return channelFuturePool.getNumIdle(); + } + + @Override + public void updateLatencyWithReadTimeOut() { + updateLatency(readTimeOut); + } + + public RpcClient getRpcClient() { + return rpcClient; + } + + public void setRpcClient(RpcClient rpcClient) { + this.rpcClient = rpcClient; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcShortChannel.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcShortChannel.java new file mode 100644 index 00000000..16f4afcf --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcShortChannel.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.channel; + +import java.util.NoSuchElementException; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.instance.ServiceInstance; + +import io.netty.channel.Channel; + +/** + * BrpcShortChannel build single & short connection with server + * and channel will be closed by brpc after communication with server + */ +public class BrpcShortChannel extends AbstractBrpcChannel { + + public BrpcShortChannel(ServiceInstance instance, RpcClient rpcClient) { + super(instance, rpcClient.getBootstrap(), rpcClient.getProtocol(), rpcClient); + } + + @Override + public Channel getChannel() throws Exception, NoSuchElementException, IllegalStateException { + Channel channel = connect(serviceInstance.getIp(), serviceInstance.getPort()); + ChannelInfo channelInfo = ChannelInfo.getOrCreateClientChannelInfo(channel); + channelInfo.setProtocol(protocol); + channelInfo.setChannelGroup(this); + return channel; + } + + @Override + public void returnChannel(Channel channel) { + } + + @Override + public void removeChannel(Channel channel) { + channel.close(); + } + + @Override + public void close() { + } + + @Override + public void updateMaxConnection(int num) { + } + + @Override + public int getCurrentMaxConnection() { + return getActiveConnectionNum(); + } + + @Override + public int getActiveConnectionNum() { + return 0; + } + + @Override + public int getIdleConnectionNum() { + return 0; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcSingleChannel.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcSingleChannel.java new file mode 100644 index 00000000..ec4015f1 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/BrpcSingleChannel.java @@ -0,0 +1,225 @@ +package com.baidu.brpc.client.channel; + +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.channel.Channel; +import lombok.extern.slf4j.Slf4j; + +/** + * BrpcSingleChannel class keeps single persistent connection with one server + */ +@Slf4j +public class BrpcSingleChannel extends AbstractBrpcChannel { + + private static final int RETRY_THRESHOLD = 2; + + private volatile Channel channel; + + private volatile Long lastTryConnectTime = 0L; + private AtomicInteger retryCount = new AtomicInteger(0); + private int connectPeriod; + + private AtomicLong failedNum = new AtomicLong(0); + private int readTimeOut; + private int latencyWindowSize; + private Queue latencyWindow; + + + private static final ExecutorService CONNECTION_SERVICE = Executors.newFixedThreadPool(3, new CustomThreadFactory( + "single-channel-connect-thread")); + + public static class ReConnectTask implements Runnable { + BrpcSingleChannel channelGroup; + Channel oldChannel; + + public ReConnectTask(BrpcSingleChannel singleChannelGroup, Channel oldChannel) { + this.channelGroup = singleChannelGroup; + this.oldChannel = oldChannel; + } + + @Override + public void run() { + if (oldChannel != channelGroup.channel) { + return; + } + // avoid busy connecting + if (System.currentTimeMillis() - channelGroup.lastTryConnectTime < channelGroup.connectPeriod + && channelGroup.retryCount.get() >= RETRY_THRESHOLD) { + return; + } + synchronized (channelGroup) { + if (oldChannel != channelGroup.channel) { + return; + } + Channel newChannel = null; + try { + newChannel = channelGroup.createChannel( + channelGroup.getServiceInstance().getIp(), + channelGroup.getServiceInstance().getPort()); + } catch (Exception e) { + log.info("failed reconnecting"); + } + if (newChannel != null) { + channelGroup.updateChannel(newChannel); + if (oldChannel != null) { + oldChannel.close(); + } + } + } + } + } + + public BrpcSingleChannel(ServiceInstance serviceInstance, RpcClient rpcClient) { + super(serviceInstance, rpcClient.getBootstrap(), rpcClient.getProtocol(), rpcClient); + RpcClientOptions rpcClientOptions = rpcClient.getRpcClientOptions(); + this.connectPeriod = rpcClientOptions.getHealthyCheckIntervalMillis(); + this.readTimeOut = rpcClientOptions.getReadTimeoutMillis(); + this.latencyWindowSize = rpcClientOptions.getLatencyWindowSizeOfFairLoadBalance(); + this.latencyWindow = new ConcurrentLinkedQueue(); + } + + @Override + public Channel getChannel() throws Exception, NoSuchElementException, IllegalStateException { + if (isNonActive(channel)) { + synchronized (this) { + if (isNonActive(channel)) { + channel = createChannel(serviceInstance.getIp(), serviceInstance.getPort()); + } + } + } + return channel; + } + + @Override + public void removeChannel(Channel channel) { + if (channel != this.channel) { + return; + } + CONNECTION_SERVICE.execute(genReconnectTask(channel)); + } + + @Override + public void updateChannel(Channel channel) { + if (channel != this.channel) { + this.channel = channel; + } + } + + private ReConnectTask genReconnectTask(Channel oldChannel) { + return new ReConnectTask(this, oldChannel); + } + + private Channel createChannel(String ip, int port) { + long currentTimeMillis = System.currentTimeMillis(); + if (currentTimeMillis - lastTryConnectTime < connectPeriod + && retryCount.getAndIncrement() >= RETRY_THRESHOLD) { + return null; + } else { + if (currentTimeMillis - lastTryConnectTime >= connectPeriod) { + refreshConnectionState(currentTimeMillis, 1); + } + Channel channel; + channel = doCreateChannel(ip, port); + refreshConnectionState(currentTimeMillis, 0); + return channel; + } + } + + private void refreshConnectionState(long currentTimeMillis, int retryCount) { + this.retryCount = new AtomicInteger(retryCount); + lastTryConnectTime = currentTimeMillis; + } + + private Channel doCreateChannel(String ip, int port) { + Channel channel = connect(ip, port); + ChannelInfo channelInfo = ChannelInfo.getOrCreateClientChannelInfo(channel); + channelInfo.setProtocol(protocol); + channelInfo.setChannelGroup(this); + return channel; + } + + @Override + public void close() { + if (channel != null) { + channel.close(); + channel = null; + } + } + + @Override + public int getCurrentMaxConnection() { + return countChannel(); + } + + @Override + public int getActiveConnectionNum() { + return countChannel(); + } + + @Override + public int getIdleConnectionNum() { + return countChannel(); + } + + @Override + public void returnChannel(Channel channel) { + // ignore + } + + @Override + public void updateMaxConnection(int num) { + // ignore + } + + private boolean isActive(Channel channel) { + return channel != null && channel.isActive(); + } + + private boolean isNonActive(Channel channel) { + return !isActive(channel); + } + + private int countChannel() { + return isActive(channel) ? 1 : 0; + } + + @Override + public long getFailedNum() { + return failedNum.get(); + } + + @Override + public void incFailedNum() { + failedNum.incrementAndGet(); + } + + @Override + public Queue getLatencyWindow() { + return latencyWindow; + } + + @Override + public void updateLatency(int latency) { + latencyWindow.add(latency); + if (latencyWindow.size() > latencyWindowSize) { + latencyWindow.poll(); + } + } + + @Override + public void updateLatencyWithReadTimeOut() { + updateLatency(readTimeOut); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/ChannelType.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/ChannelType.java new file mode 100644 index 00000000..578e7031 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/channel/ChannelType.java @@ -0,0 +1,24 @@ +package com.baidu.brpc.client.channel; + +public enum ChannelType { + + POOLED_CONNECTION(0, "POOLED_CONNECTION"), + SINGLE_CONNECTION(1, "SINGLE_CONNECTION"), + SHORT_CONNECTION(2, "SHORT_CONNECTION"); + + private int id; + private String name; + + ChannelType(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/ClientWorkTask.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/ClientWorkTask.java new file mode 100644 index 00000000..114ab28f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/ClientWorkTask.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.handler; + +import java.lang.reflect.Method; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushPacket; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.server.ServiceManager; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Setter +@Getter +@AllArgsConstructor +public class ClientWorkTask implements Runnable { + private RpcClient rpcClient; + private Object packet; + private Protocol protocol; + private ChannelHandlerContext ctx; + + @Override + public void run() { + // 只有server push协议下,有可能受到request类型 + if (protocol instanceof ServerPushProtocol) { + // 区分类型 + SPHead spHead = ((ServerPushPacket) packet).getSpHead(); + if (spHead.getType() == SPHead.TYPE_PUSH_REQUEST) { + handlePushRequest(); + return; + } + } + + Response response; + try { + response = protocol.decodeResponse(packet, ctx); + } catch (Exception e) { + log.warn("decode response failed:", e); + return; + } + + if (response.getRpcFuture() != null) { + log.debug("handle response, correlationId={}", response.getCorrelationId()); + RpcFuture future = response.getRpcFuture(); + future.handleResponse(response); + } else { + log.warn("rpcFuture is null, server return to slow, correlationId={}", response.getCorrelationId()); + } + } + + /** + * 收到push请求的处理方法 + */ + private void handlePushRequest() { + + Request request = null; + Response response = protocol.createResponse(); + try { + request = protocol.decodeRequest(packet); + } catch (Exception ex) { + // throw request + log.warn("decode request failed:", ex); + response.setException(ex); + } finally { + if (request != null && request.getException() != null) { + response.setException(request.getException()); + } + } + + RpcContext rpcContext = null; + request.setChannel(ctx.channel()); + if (request.getBinaryAttachment() != null + || request.getKvAttachment() != null) { + rpcContext = RpcContext.getContext(); + if (request.getBinaryAttachment() != null) { + rpcContext.setRequestBinaryAttachment(request.getBinaryAttachment()); + } + if (request.getKvAttachment() != null) { + rpcContext.setRequestKvAttachment(request.getKvAttachment()); + } + rpcContext.setRemoteAddress(ctx.channel().remoteAddress()); + } + + response.setLogId(request.getLogId()); + response.setCorrelationId(request.getCorrelationId()); + response.setCompressType(request.getCompressType()); + response.setException(request.getException()); + response.setRpcMethodInfo(request.getRpcMethodInfo()); + + String serviceName = request.getServiceName(); + String methodName = request.getMethodName(); + RpcMethodInfo service = ServiceManager.getInstance().getService(serviceName, methodName); + Method targetMethod = request.getTargetMethod(); + Object t = service.getTarget(); + Object result = null; + try { + result = targetMethod.invoke(t, request.getArgs()); + } catch (Exception e) { + log.error("exception :", e); + } + response.setResult(result); + try { + ByteBuf byteBuf = protocol.encodeResponse(request, response); + ChannelFuture channelFuture = ctx.channel().writeAndFlush(byteBuf); + protocol.afterResponseSent(request, response, channelFuture); + } catch (Exception ex) { + log.warn("send response failed:", ex); + } + + if (rpcContext != null) { + rpcContext.reset(); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/IdleChannelHandler.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/IdleChannelHandler.java new file mode 100644 index 00000000..e141db53 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/IdleChannelHandler.java @@ -0,0 +1,20 @@ +package com.baidu.brpc.client.handler; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleStateEvent; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class IdleChannelHandler extends ChannelInboundHandlerAdapter { + + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + Channel channel = ctx.channel(); + channel.close(); + } else { + super.userEventTriggered(ctx, evt); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/RpcClientHandler.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/RpcClientHandler.java new file mode 100644 index 00000000..f70da35c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/handler/RpcClientHandler.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.handler; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; + +@ChannelHandler.Sharable +@Slf4j +public class RpcClientHandler extends SimpleChannelInboundHandler { + + private RpcClient rpcClient; + + public RpcClientHandler(RpcClient rpcClient) { + this.rpcClient = rpcClient; + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, Object in) throws Exception { + + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + ByteBuf msg = (ByteBuf) in; + int len = msg.readableBytes(); + if (len > 0) { + channelInfo.getRecvBuf().addBuffer(msg.retain()); + } + + ClientWorkTask[] tasks = new ClientWorkTask[64]; + int i = 0; + while (channelInfo.getRecvBuf().readableBytes() > 0) { + try { + Object packet = channelInfo.getProtocol().decode(ctx, channelInfo.getRecvBuf(), false); + ClientWorkTask task = new ClientWorkTask(rpcClient, packet, channelInfo.getProtocol(), ctx); + tasks[i++] = task; + if (i == 64) { + rpcClient.getWorkThreadPool().submit(tasks, 0, i); + i = 0; + } + } catch (NotEnoughDataException ex1) { + break; + } catch (TooBigDataException ex2) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex2); + } catch (BadSchemaException ex3) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex3); + } + } + + if (i > 0) { + rpcClient.getWorkThreadPool().submit(tasks, 0, i); + } + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + final ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + if (channelInfo == null) { + log.warn("clientChannelInfo is missing"); + return; + } + + String ip = channelInfo.getChannelGroup().getServiceInstance().getIp(); + int port = channelInfo.getChannelGroup().getServiceInstance().getPort(); + final String errMsg = String.format("channel is non active, ip=%s,port=%d", ip, port); + log.debug(errMsg); + rpcClient.triggerCallback(new Runnable() { + @Override + public void run() { + RpcException ex = new RpcException(RpcException.NETWORK_EXCEPTION, errMsg); + channelInfo.handleChannelException(ex); + } + }); + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, final Throwable cause) throws Exception { + log.info(cause.getMessage()); + + final ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + if (channelInfo != null) { + rpcClient.triggerCallback(new Runnable() { + @Override + public void run() { + RpcException ex = new RpcException(RpcException.SERIALIZATION_EXCEPTION, cause); + channelInfo.handleChannelException(ex); + } + }); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/BasicInstanceProcessor.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/BasicInstanceProcessor.java new file mode 100644 index 00000000..aada2296 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/BasicInstanceProcessor.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.instance; + +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.BrpcChannelFactory; +import com.baidu.brpc.client.RpcClient; + +public class BasicInstanceProcessor implements InstanceProcessor { + private CopyOnWriteArraySet instances; + private CopyOnWriteArrayList instanceChannels; + private ConcurrentMap instanceChannelMap; + private Lock lock; + private RpcClient rpcClient; + + public BasicInstanceProcessor(RpcClient rpcClient) { + this.instances = new CopyOnWriteArraySet(); + this.instanceChannels = new CopyOnWriteArrayList(); + this.instanceChannelMap = new ConcurrentHashMap(); + this.lock = new ReentrantLock(); + this.rpcClient = rpcClient; + } + + @Override + public void addInstance(ServiceInstance instance) { + lock.lock(); + try { + if (instances.add(instance)) { + BrpcChannel brpcChannel = BrpcChannelFactory.createChannel(instance, rpcClient); + instanceChannels.add(brpcChannel); + instanceChannelMap.putIfAbsent(instance, brpcChannel); + } + } finally { + lock.unlock(); + } + } + + @Override + public void addInstances(Collection addList) { + for (ServiceInstance instance : addList) { + addInstance(instance); + } + } + + @Override + public void deleteInstances(Collection deleteList) { + for (ServiceInstance instance : deleteList) { + deleteInstance(instance); + } + } + + private void deleteInstance(ServiceInstance instance) { + lock.lock(); + try { + if (instances.remove(instance)) { + Iterator iterator = instanceChannels.iterator(); + while (iterator.hasNext()) { + BrpcChannel brpcChannel = iterator.next(); + if (brpcChannel.getServiceInstance().equals(instance)) { + brpcChannel.close(); + instanceChannels.remove(brpcChannel); + instanceChannelMap.remove(instance); + break; + } + } + } + } finally { + lock.unlock(); + } + } + + @Override + public CopyOnWriteArraySet getInstances() { + return instances; + } + + @Override + public CopyOnWriteArrayList getHealthyInstanceChannels() { + return instanceChannels; + } + + @Override + public CopyOnWriteArrayList getUnHealthyInstanceChannels() { + return instanceChannels; + } + + @Override + public ConcurrentMap getInstanceChannelMap() { + return instanceChannelMap; + } + + @Override + public void stop() { + for (BrpcChannel brpcChannel : instanceChannels) { + brpcChannel.close(); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/Endpoint.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/Endpoint.java new file mode 100644 index 00000000..183d3ec6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/Endpoint.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.instance; + +import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import lombok.Getter; +import lombok.Setter; + +/** + * Created by wenweihu86 on 2017/5/17. + */ +@Getter +@Setter +public class Endpoint { + + private String ip; + + private int port; + + public Endpoint() { + } + + public Endpoint(String ip, int port) { + this.ip = ip; + this.port = port; + } + + public Endpoint(String address) { + Validate.notEmpty(address); + String[] splits = address.split(":"); + Validate.isTrue(2 == splits.length); + this.ip = splits[0]; + this.port = Integer.valueOf(splits[1]); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(ip) + .append(port) + .toHashCode(); + } + + @Override + public boolean equals(Object object) { + boolean flag = false; + if (object != null && Endpoint.class.isAssignableFrom(object.getClass())) { + Endpoint rhs = (Endpoint) object; + flag = new EqualsBuilder() + .append(ip, rhs.ip) + .append(port, rhs.port) + .isEquals(); + } + return flag; + } + + @Override + public String toString() { + return String.format("EndPoint{\'%s:%d\'}", ip, port); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/EnhancedInstanceProcessor.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/EnhancedInstanceProcessor.java new file mode 100644 index 00000000..e85c159c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/EnhancedInstanceProcessor.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.instance; + +import java.io.IOException; +import java.net.Socket; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.BrpcChannelFactory; +import com.baidu.brpc.client.loadbalance.FairStrategy; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.thread.ClientHealthCheckTimerInstance; + +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EnhancedInstanceProcessor implements InstanceProcessor { + private RpcClient rpcClient; + private CopyOnWriteArraySet instances; + private CopyOnWriteArrayList healthyInstanceChannels; + private CopyOnWriteArrayList unhealthyInstanceChannels; + private ConcurrentMap instanceChannelMap; + private Lock lock; + private Timer healthCheckTimer; + private volatile boolean stop = false; + + public EnhancedInstanceProcessor(RpcClient rpcClient) { + this.rpcClient = rpcClient; + this.instances = new CopyOnWriteArraySet(); + this.healthyInstanceChannels = new CopyOnWriteArrayList(); + this.unhealthyInstanceChannels = new CopyOnWriteArrayList(); + this.instanceChannelMap = new ConcurrentHashMap(); + this.lock = new ReentrantLock(); + healthCheckTimer = ClientHealthCheckTimerInstance.getOrCreateInstance(); + init(); + } + + private void init() { + // start healthy check timer + healthCheckTimer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + if (!stop) { + List newHealthyInstanceChannels = new ArrayList(); + Iterator iter = unhealthyInstanceChannels.iterator(); + while (iter.hasNext()) { + BrpcChannel instance = iter.next(); + boolean isHealthy = isInstanceHealthy(instance.getServiceInstance().getIp(), + instance.getServiceInstance().getPort()); + if (isHealthy) { + newHealthyInstanceChannels.add(instance); + } + } + + List newUnhealthyInstanceChannels = new ArrayList(); + iter = healthyInstanceChannels.iterator(); + while (iter.hasNext()) { + BrpcChannel instance = iter.next(); + boolean isHealthy = isInstanceHealthy(instance.getServiceInstance().getIp(), + instance.getServiceInstance().getPort()); + if (!isHealthy) { + newUnhealthyInstanceChannels.add(instance); + } + } + + lock.lock(); + try { + if (newUnhealthyInstanceChannels.size() > 0) { + List effectiveInstances = new ArrayList(); + for (BrpcChannel brpcChannel : newUnhealthyInstanceChannels) { + if (instances.contains(brpcChannel.getServiceInstance())) { + effectiveInstances.add(brpcChannel); + } + } + healthyInstanceChannels.removeAll(effectiveInstances); + unhealthyInstanceChannels.addAll(effectiveInstances); + notifyInvalidInstance(effectiveInstances); + } + + if (newHealthyInstanceChannels.size() > 0) { + List effectiveInstances = new ArrayList(); + for (BrpcChannel brpcChannel : newHealthyInstanceChannels) { + if (instances.contains(brpcChannel.getServiceInstance())) { + effectiveInstances.add(brpcChannel); + } + } + healthyInstanceChannels.addAll(effectiveInstances); + unhealthyInstanceChannels.removeAll(effectiveInstances); + } + } finally { + lock.unlock(); + } + + healthCheckTimer.newTimeout(this, + rpcClient.getRpcClientOptions().getHealthyCheckIntervalMillis(), + TimeUnit.MILLISECONDS); + } + + } + }, + rpcClient.getRpcClientOptions().getHealthyCheckIntervalMillis(), + TimeUnit.MILLISECONDS); + } + + public void addInstance(ServiceInstance instance) { + lock.lock(); + try { + if (instances.add(instance)) { + BrpcChannel brpcChannel = BrpcChannelFactory.createChannel(instance, rpcClient); + healthyInstanceChannels.add(brpcChannel); + instanceChannelMap.putIfAbsent(instance, brpcChannel); + } else { + log.debug("endpoint already exist, {}:{}", instance.getIp(), instance.getPort()); + } + } finally { + lock.unlock(); + } + } + + @Override + public void addInstances(Collection addList) { + for (ServiceInstance instance : addList) { + addInstance(instance); + } + } + + @Override + public void deleteInstances(Collection deleteList) { + List removedInstanceChannels = new ArrayList(); + for (ServiceInstance instance : deleteList) { + BrpcChannel brpcChannel = deleteInstance(instance); + if (brpcChannel != null) { + removedInstanceChannels.add(brpcChannel); + } + } + // close the channel pool after 1 second, so that request can be finished + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + log.warn("InterruptedException:", ex); + } + for (BrpcChannel brpcChannel : removedInstanceChannels) { + brpcChannel.close(); + } + } + + @Override + public CopyOnWriteArraySet getInstances() { + return instances; + } + + @Override + public CopyOnWriteArrayList getHealthyInstanceChannels() { + return healthyInstanceChannels; + } + + @Override + public CopyOnWriteArrayList getUnHealthyInstanceChannels() { + return unhealthyInstanceChannels; + } + + @Override + public ConcurrentMap getInstanceChannelMap() { + return instanceChannelMap; + } + + @Override + public void stop() { + stop = true; + for (BrpcChannel brpcChannel : healthyInstanceChannels) { + brpcChannel.close(); + } + for (BrpcChannel brpcChannel : unhealthyInstanceChannels) { + brpcChannel.close(); + } + } + + private boolean isInstanceHealthy(String ip, int port) { + boolean isHealthy = false; + Socket socket = null; + try { + socket = new Socket(ip, port); + isHealthy = true; + } catch (Exception e) { + log.warn("Recover socket test for {}:{} failed. message:{}", + ip, port, e.getMessage()); + isHealthy = false; + } finally { + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug(e.getMessage(), e); + } + } + } + return isHealthy; + } + + private BrpcChannel deleteInstance(ServiceInstance instance) { + lock.lock(); + try { + if (instances.remove(instance)) { + instanceChannelMap.remove(instance); + BrpcChannel brpcChannel = removeInstanceChannel(healthyInstanceChannels, instance); + if (brpcChannel == null) { + brpcChannel = removeInstanceChannel(unhealthyInstanceChannels, instance); + } + if (brpcChannel == null) { + log.error("instance exist, but channel not exist"); + } else { + // notify the fair load balance strategy + notifyInvalidInstance(Arrays.asList(brpcChannel)); + } + return brpcChannel; + } + } finally { + lock.unlock(); + } + return null; + } + + private void notifyInvalidInstance(List invalidInstances) { + if (rpcClient.getRpcClientOptions().getLoadBalanceType() == LoadBalanceStrategy.LOAD_BALANCE_FAIR) { + ((FairStrategy) rpcClient.getLoadBalanceStrategy()).markInvalidInstance(invalidInstances); + } + } + + private BrpcChannel removeInstanceChannel( + CopyOnWriteArrayList checkedInstanceChannels, + ServiceInstance instance) { + Iterator iterator = checkedInstanceChannels.iterator(); + while (iterator.hasNext()) { + BrpcChannel brpcChannel = iterator.next(); + if (brpcChannel.getServiceInstance().equals(instance)) { + checkedInstanceChannels.remove(brpcChannel); + return brpcChannel; + } + } + return null; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/InstanceProcessor.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/InstanceProcessor.java new file mode 100644 index 00000000..b2d3dc68 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/InstanceProcessor.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.instance; + +import com.baidu.brpc.client.channel.BrpcChannel; + +import java.util.Collection; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; + +public interface InstanceProcessor { + void addInstance(ServiceInstance instance); + + void addInstances(Collection addList); + + void deleteInstances(Collection deleteList); + + CopyOnWriteArraySet getInstances(); + + CopyOnWriteArrayList getHealthyInstanceChannels(); + + CopyOnWriteArrayList getUnHealthyInstanceChannels(); + + ConcurrentMap getInstanceChannelMap(); + + void stop(); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/ServiceInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/ServiceInstance.java new file mode 100644 index 00000000..8448c014 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/instance/ServiceInstance.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.instance; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class ServiceInstance extends Endpoint { + /** + * instance tag, such as sharding info. + * used by bns naming service. + */ + private String tag; + + public ServiceInstance() { + super(); + } + + public ServiceInstance(String ip, int port) { + super(ip, port); + } + + public ServiceInstance(String address) { + super(address); + } + + public ServiceInstance(Endpoint endpoint) { + super(endpoint.getIp(), endpoint.getPort()); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairLoadBalanceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairLoadBalanceFactory.java new file mode 100644 index 00000000..b26adb6f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairLoadBalanceFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +public class FairLoadBalanceFactory implements LoadBalanceFactory { + + @Override + public Integer getLoadBalanceType() { + return LoadBalanceStrategy.LOAD_BALANCE_FAIR; + } + + @Override + public LoadBalanceStrategy createLoadBalance() { + return new FairStrategy(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairStrategy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairStrategy.java new file mode 100644 index 00000000..03938d0c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/FairStrategy.java @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.utils.CollectionUtils; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.extern.slf4j.Slf4j; + +/** + * Fair load balance strategy aims to more reasonable distribution of traffic. + * The principle of traffic distribution is not the same as pv, but the distribution of traffic according to performance, + * the performance of the machine with multi-point traffic, the poor performance of the machine with less point traffic, + * the same machine traffic with the same performance, and finally the service performance of all nodes tends to balance, + * there will be no slow nodes to improve the overall performance of the service. + * + *

Algorithm overview: + * The fair load balancing policy dynamically adjusts the weight of each server and divides it by weight. + * Rpc client maintains a latency window record rpc time for each server, after processing a traffic, the server + * updates its own window. If the mean value of the service in the window > the overall mean of the service, reduce its own weight. + * On the contrary, increase its own weight. When the window is not full, the polling does not adjust the weight. + * + * @author wangjiayin + * @since 2018-09-03 + */ +@Slf4j +public class FairStrategy implements LoadBalanceStrategy { + + private static final int TIMER_DELAY = 60; + + /** + * The binary tree used to save weight number for each node. + * We use a CopyOnWriteArrayList to safely lockless update the weight tree, + * The first element fo the CopyOnWriteArrayList is useful. + * The leaf elements of the weight tree are the real rpc servers, and the parent elements of the weight used + * to save the sum weight of its left and right child's weight. + * The root element's weight sum is the total sum of every leaf element's weight. + * + *

The weight tree can achieve time complexity at the O(logN) level, and 1000 servers require only 11 memory accesses. + */ + private CopyOnWriteArrayList treeContainer; + + private volatile Timer timer; + + private RpcClient rpcClient; + + private int latencyWindowSize; + + // {@see RpcClientOptions#activeInstancesRatioOfFairLoadBalance} + private float activeInstancesRatio; + + // fair strategy will not work if the instances is less the minInstancesNum + private int minInstancesNum = 3; + + private CopyOnWriteArrayList invalidInstances; + + private Random random = new Random(System.currentTimeMillis()); + + @Override + public void init(RpcClient rpcClient) { + if (timer == null) { + synchronized (this) { + if (timer == null) { + timer = new HashedWheelTimer(new CustomThreadFactory("fairStrategy-timer-thread")); + timer.newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) { + updateWeightTree(); + timer.newTimeout(this, TIMER_DELAY, TimeUnit.SECONDS); + } + }, TIMER_DELAY, TimeUnit.SECONDS); + this.rpcClient = rpcClient; + treeContainer = new CopyOnWriteArrayList(); + invalidInstances = new CopyOnWriteArrayList(); + latencyWindowSize = rpcClient.getRpcClientOptions().getLatencyWindowSizeOfFairLoadBalance(); + activeInstancesRatio = rpcClient.getRpcClientOptions().getActiveInstancesRatioOfFairLoadBalance(); + if (latencyWindowSize <= 1) { + throw new IllegalArgumentException("latencyWindowSize must be greater than 1"); + } + } + } + } + } + + @Override + public BrpcChannel selectInstance( + Request request, + List instances, + Set selectedInstances) { + + if (treeContainer.size() == 0) { + return randomSelect(instances); + } + + try { + Node root = treeContainer.get(0); + BrpcChannel selectedChannelGroup = fairSelect(root); + // the invalidInstances list size is not very large. + if (invalidInstances.contains(selectedChannelGroup)) { + // if the selected node is an invalid one, means the weight tree has not yet updated. + // random reselect a new one + log.debug("the selected one is invalid, begin to random reselect a new one..."); + return randomSelect(instances); + } + return selectedChannelGroup; + } catch (Exception e) { + log.warn("FairStrategy select channel failed.", e); + return randomSelect(instances); + } + + } + + @Override + public void destroy() { + if (timer != null) { + timer.stop(); + } + } + + /** + * Since the weight tree will update by a period of time, so if there's any invalid instance, + * the business should notify the fair strategy. + */ + public void markInvalidInstance(List instances) { + this.invalidInstances.addAll(instances); + } + + protected BrpcChannel randomSelect(List instances) { + long instanceNum = instances.size(); + if (instanceNum == 0) { + return null; + } + int index = (int) (getRandomLong() % instanceNum); + return instances.get(index); + } + + protected long getRandomLong() { + long randomIndex = random.nextLong(); + if (randomIndex < 0) { + randomIndex = 0 - randomIndex; + } + return randomIndex; + } + + protected BrpcChannel fairSelect(Node root) { + int max = root.weight; + int randomWeight = random.nextInt(max); + Node selectNode = searchNode(root, randomWeight); + return selectNode.server; + } + + protected Node searchNode(Node parent, int weight) { + + if (parent.left == null) { + return parent; + } + + if (parent.right == null) { + return parent.left; + } + + if (parent.left.weight >= weight) { + return searchNode(parent.left, weight); + } else { + return searchNode(parent.right, weight - parent.left.weight); + } + + } + + /** + * Update weight of each node of the tree. + * By create a new tree and insert into the head of the {@link #treeContainer} + */ + protected void updateWeightTree() { + + log.debug("begin to updateWeightTree..."); + + int timeOut = rpcClient.getRpcClientOptions().getReadTimeoutMillis(); + // Create the leaf nodes of the weight tree + Queue leafNodes = new LinkedList(); + if (CollectionUtils.isEmpty(rpcClient.getHealthyInstances())) { + // if there're no healthy servers, skip create weight, use the random select algorithm instead + return; + } + + // the instances to build the weight tree + List fullWindowInstances = new LinkedList(); + + for (BrpcChannel group : rpcClient.getHealthyInstances()) { + Queue window = group.getLatencyWindow(); + // skip instances whose window is not full + if (window.size() == latencyWindowSize) { + fullWindowInstances.add(group); + } + } + + // some conditions must be satisfied, if not, the fair strategy will not work and use random strategy instead + if (fullWindowInstances.size() < minInstancesNum + || fullWindowInstances.size() * 1.0 / rpcClient.getHealthyInstances().size() < activeInstancesRatio) { + treeContainer = new CopyOnWriteArrayList(); + invalidInstances = new CopyOnWriteArrayList(); + return; + } + + // begin to build the weight tree + for (BrpcChannel group : fullWindowInstances) { + int weight = calculateWeight(group, timeOut); + leafNodes.add(new Node(group.hashCode(), weight, true, group)); + } + + // Now begin to create a new weight tree + Node root = generateWeightTreeByLeafNodes(leafNodes); + + // Insert the new tree into the head of the container + treeContainer.add(0, root); + while (treeContainer.size() > 1) { + // Remove the old weight tree + treeContainer.remove(1); + } + + // Since the weight tree has updated by healthy instances, we need to update invalid instances too. + // Although there maybe new invalid instances added while updating the weight tree, for simplicity, + // we just remove all invalid instances, at least brpc-java has the retry feature. + invalidInstances = new CopyOnWriteArrayList(); + } + + /** + * Calculate the weight of a rpc server + * + * @param group The BrpcChannel instance of a rpc server + * @param timeOut Read timeout in millis + * @return Weight num + */ + protected int calculateWeight(BrpcChannel group, int timeOut) { + Queue window = group.getLatencyWindow(); + int avgLatency = 0; + for (int latency : window) { + avgLatency += latency; + } + // calculate the average latency + avgLatency = avgLatency / window.size(); + // normalization to 1-100, to prevent inaccurate calculation of timer, plus a 10ms to the timeout num + avgLatency = avgLatency * 100 / (timeOut + 10); + // calculate the final weight + int weight = 100 - avgLatency; + return weight > 0 ? weight : 1; + } + + /** + * generate the tree by leaf nodes + * the leaf nodes are the real rpc servers + * the parent nodes used to calculate the sum of it's children's weight + * + * @param leafNodes leaf nodes list + * @return the root node of the tree + */ + protected Node generateWeightTreeByLeafNodes(Queue leafNodes) { + + Queue nodes = new LinkedList(leafNodes); + if (leafNodes.size() % 2 == 1) { + nodes.add(Node.none); + } + + Node root = new Node(); + + while (nodes.size() > 0) { + + Node left = nodes.poll(); + Node right = nodes.poll(); + + if (!left.isLeaf && right == null) { + root = left; + break; + } + + Node parent = new Node(0, 0, false); + parent.left = left; + left.parent = parent; + + if (right != null && right != Node.none) { + parent.right = right; + parent.weight = left.weight + right.weight; + right.parent = parent; + } else { + parent.weight = left.weight; + } + + nodes.add(parent); + } + + return root; + } + + /** + * The weight tree node + */ + static class Node { + // empty node + static Node none = new Node(); + int serverId; + int weight; + boolean isLeaf; + Node parent; + Node left; + Node right; + BrpcChannel server; + + public Node() { + } + + public Node(int serverId, int weight, boolean isLeaf) { + this.serverId = serverId; + this.weight = weight; + this.isLeaf = isLeaf; + } + + public Node(int serverId, int weight, boolean isLeaf, BrpcChannel server) { + this.serverId = serverId; + this.weight = weight; + this.isLeaf = isLeaf; + this.server = server; + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceFactory.java new file mode 100644 index 00000000..242cd872 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceFactory.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +public interface LoadBalanceFactory { + Integer getLoadBalanceType(); + LoadBalanceStrategy createLoadBalance(); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceManager.java new file mode 100644 index 00000000..a686a6e0 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class LoadBalanceManager { + private static volatile LoadBalanceManager instance; + private Map loadBalanceFactoryMap; + + public static LoadBalanceManager getInstance() { + if (instance == null) { + synchronized(LoadBalanceManager.class) { + if (instance == null) { + instance = new LoadBalanceManager(); + } + } + } + return instance; + } + + private LoadBalanceManager() { + loadBalanceFactoryMap = new HashMap(); + } + + public void registerLoadBalanceFactory(LoadBalanceFactory factory) { + Integer loadBalanceType = factory.getLoadBalanceType(); + if (loadBalanceFactoryMap.get(loadBalanceType) != null) { + throw new RuntimeException("load balance factory already exist:" + loadBalanceType); + } + loadBalanceFactoryMap.put(loadBalanceType, factory); + log.info("register load balance factory:{} success", factory.getClass().getSimpleName()); + } + + public LoadBalanceFactory getLoadBalanceFactory(Integer loadBalanceType) { + return loadBalanceFactoryMap.get(loadBalanceType); + } + + public LoadBalanceStrategy createLoadBalance(Integer loadBalanceType) { + LoadBalanceFactory factory = loadBalanceFactoryMap.get(loadBalanceType); + if (factory == null) { + throw new IllegalArgumentException("load balance not exist:" + loadBalanceType); + } + return factory.createLoadBalance(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceStrategy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceStrategy.java new file mode 100644 index 00000000..4b37bd40 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceStrategy.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.List; +import java.util.Set; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.protocol.Request; + +/** + * load balance strategy interface + */ +public interface LoadBalanceStrategy { + // default supported load balance type + int LOAD_BALANCE_RANDOM = 0; + int LOAD_BALANCE_ROUND_ROBIN = 1; + int LOAD_BALANCE_WEIGHT = 2; + int LOAD_BALANCE_FAIR = 3; + + void init(RpcClient rpcClient); + + /** + * select instance channel from total instances + * @param request request info + * @param instances total instances, often are all healthy instances + * @param selectedInstances instances which have been selected. + * @return the best instance channel + */ + BrpcChannel selectInstance( + Request request, + List instances, + Set selectedInstances); + + void destroy(); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceType.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceType.java new file mode 100644 index 00000000..f7528649 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/LoadBalanceType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +/** + * Created by huwenwei on 2017/9/29. + * please use constants of {@link LoadBalanceStrategy} instead. + */ +@Deprecated +public enum LoadBalanceType { + + RANDOM(0, "RANDOM", new RandomStrategy()), + ROUND_ROBIN(1, "ROUND_ROBIN", new RoundRobinStrategy()), + WEIGHT(2, "WEIGHT", new WeightStrategy()), + FAIR(3, "FAIR", new FairStrategy()); + + private int id; + private String name; + private LoadBalanceStrategy strategy; + + LoadBalanceType(int id, String name, LoadBalanceStrategy strategy) { + this.id = id; + this.name = name; + this.strategy = strategy; + } + + public static LoadBalanceType parse(int id) { + for (LoadBalanceType item : LoadBalanceType.values()) { + if (item.getId() == id) { + return item; + } + } + throw new IllegalArgumentException("unknown load balance id"); + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public LoadBalanceStrategy getStrategy() { + return strategy; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomLoadBalanceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomLoadBalanceFactory.java new file mode 100644 index 00000000..04ee322a --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomLoadBalanceFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +public class RandomLoadBalanceFactory implements LoadBalanceFactory { + + @Override + public Integer getLoadBalanceType() { + return LoadBalanceStrategy.LOAD_BALANCE_RANDOM; + } + + @Override + public LoadBalanceStrategy createLoadBalance() { + return new RandomStrategy(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomStrategy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomStrategy.java new file mode 100644 index 00000000..40935baa --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RandomStrategy.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import org.apache.commons.collections4.CollectionUtils; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.protocol.Request; + +/** + * Simple random select load balance strategy implementation + */ +public class RandomStrategy implements LoadBalanceStrategy { + private final Random random = new Random(); + + @Override + public void init(RpcClient rpcClient) { + } + + @Override + public BrpcChannel selectInstance( + Request request, + List instances, + Set selectedInstances) { + if (CollectionUtils.isEmpty(instances)) { + return null; + } + + Collection toBeSelectedInstances = null; + if (selectedInstances == null) { + toBeSelectedInstances = instances; + } else { + toBeSelectedInstances = CollectionUtils.subtract(instances, selectedInstances); + } + + int instanceNum = toBeSelectedInstances.size(); + if (instanceNum == 0) { + toBeSelectedInstances = instances; + instanceNum = toBeSelectedInstances.size(); + } + + if (instanceNum == 0) { + return null; + } + int index = getRandomInt(instanceNum); + BrpcChannel brpcChannel = toBeSelectedInstances.toArray(new BrpcChannel[0])[index]; + return brpcChannel; + } + + @Override + public void destroy() { + } + + private int getRandomInt(int bound) { + int randomIndex = random.nextInt(bound); + return randomIndex; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinLoadBalanceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinLoadBalanceFactory.java new file mode 100644 index 00000000..9dd5f5a2 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinLoadBalanceFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +public class RoundRobinLoadBalanceFactory implements LoadBalanceFactory { + + @Override + public Integer getLoadBalanceType() { + return LoadBalanceStrategy.LOAD_BALANCE_ROUND_ROBIN; + } + + @Override + public LoadBalanceStrategy createLoadBalance() { + return new RoundRobinStrategy(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinStrategy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinStrategy.java new file mode 100644 index 00000000..8b6b6f92 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/RoundRobinStrategy.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.protocol.Request; + +/** + * Round-robin load balance strategy implementation + */ +public class RoundRobinStrategy implements LoadBalanceStrategy { + + private AtomicLong counter = new AtomicLong(0); + + @Override + public void init(RpcClient rpcClient) { + + } + + @Override + public BrpcChannel selectInstance( + Request request, + List instances, + Set selectedInstances) { + long instanceNum = instances.size(); + if (instanceNum == 0) { + return null; + } + int index = (int) (counter.getAndIncrement() % instanceNum); + BrpcChannel channelGroup = instances.get(index); + return channelGroup; + } + + @Override + public void destroy() { + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightLoadBalanceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightLoadBalanceFactory.java new file mode 100644 index 00000000..bd7685a4 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightLoadBalanceFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +public class WeightLoadBalanceFactory implements LoadBalanceFactory { + + @Override + public Integer getLoadBalanceType() { + return LoadBalanceStrategy.LOAD_BALANCE_WEIGHT; + } + + @Override + public LoadBalanceStrategy createLoadBalance() { + return new WeightStrategy(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightStrategy.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightStrategy.java new file mode 100644 index 00000000..d9c67eb9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/loadbalance/WeightStrategy.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.List; +import java.util.Random; +import java.util.Set; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.protocol.Request; + +/** + * Simple weight load balance strategy implementation + * The channelGroup which has less failedNum will have the more probability + */ +public class WeightStrategy implements LoadBalanceStrategy { + + private Random random = new Random(System.currentTimeMillis()); + + @Override + public void init(RpcClient rpcClient) { + + } + + @Override + public BrpcChannel selectInstance( + Request request, + List instances, + Set selectedInstances) { + long instanceNum = instances.size(); + if (instanceNum == 0) { + return null; + } + + long sum = 0; + for (BrpcChannel instance : instances) { + sum += getWeight(instance.getFailedNum()); + } + long randWeight = random.nextLong() % sum; + for (BrpcChannel channelGroup : instances) { + randWeight -= getWeight(channelGroup.getFailedNum()); + if (randWeight <= 0) { + return channelGroup; + } + } + + return null; + } + + @Override + public void destroy() { + } + + private long getWeight(long failedNum) { + return 1000000000 / (failedNum + 1); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/client/pool/ChannelPooledObjectFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/client/pool/ChannelPooledObjectFactory.java new file mode 100644 index 00000000..43f9255f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/client/pool/ChannelPooledObjectFactory.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.pool; + +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.impl.DefaultPooledObject; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.channel.BrpcChannel; + +import io.netty.channel.Channel; +import lombok.extern.slf4j.Slf4j; + +/** + * Channel pool for the rpc client. + * Base on apache.commons.pool. + */ +@Slf4j +public class ChannelPooledObjectFactory extends BasePooledObjectFactory { + + private BrpcChannel channelGroup; + + private String ip; + + private int port; + + public ChannelPooledObjectFactory(BrpcChannel channelGroup, String ip, int port) { + this.channelGroup = channelGroup; + this.ip = ip; + this.port = port; + } + + @Override + public Channel create() throws Exception { + Channel channel = channelGroup.connect(ip, port); + ChannelInfo channelInfo = ChannelInfo.getOrCreateClientChannelInfo(channel); + channelInfo.setChannelGroup(channelGroup); + channelInfo.setProtocol(channelGroup.getProtocol()); + return channel; + } + + @Override + public PooledObject wrap(Channel obj) { + return new DefaultPooledObject(obj); + } + + @Override + public void destroyObject(PooledObject p) throws Exception { + Channel channel = p.getObject(); + if (channel != null && channel.isOpen() && channel.isActive()) { + channel.close(); + } + channel = null; + } + + public boolean validateObject(PooledObject p) { + Channel channel = p.getObject(); + return channel != null && channel.isOpen() && channel.isActive(); + } + +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/Compress.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/Compress.java new file mode 100644 index 00000000..d83e6176 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/Compress.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; + +import java.io.IOException; + +public interface Compress { + /** + * client端encode request并压缩 + * @param proto request + * @param rpcMethodInfo rpc method信息 + * @return 序列化后buf + * @throws IOException 序列化失败 + */ + ByteBuf compressInput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException; + + /** + * client端解压缩并反序列化response + * @param byteBuf response buffer + * @param rpcMethodInfo rpc method信息 + * @return response对象 + * @throws IOException 反序列化失败 + */ + Object uncompressOutput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException; + + Object uncompressOutput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException; + + Object uncompressOutput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException; + + /** + * server序列化response并压缩 + * @param proto response对象 + * @param rpcMethodInfo rpc method信息 + * @return 序列化buffer + * @throws IOException 序列化异常 + */ + ByteBuf compressOutput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException; + + /** + * server端解压缩并decode request + * @param byteBuf request buffer + * @param rpcMethodInfo rpc method信息 + * @return 请求对象 + * @throws IOException 反序列化失败 + */ + Object uncompressInput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException; + + Object uncompressInput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException; + + Object uncompressInput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/CompressManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/CompressManager.java new file mode 100644 index 00000000..389a28bd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/CompressManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.Options; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CompressManager { + private static final int MAX_COMPRESS_NUM = 16; + private static volatile CompressManager instance; + private Compress[] compressArray; + private int compressNum; + + public static CompressManager getInstance() { + if (instance == null) { + synchronized(CompressManager.class) { + if (instance == null) { + instance = new CompressManager(); + } + } + } + return instance; + } + + private CompressManager() { + compressArray = new Compress[MAX_COMPRESS_NUM]; + compressArray[Options.CompressType.COMPRESS_TYPE_NONE_VALUE] = new NoneCompress(); + compressArray[Options.CompressType.COMPRESS_TYPE_GZIP_VALUE] = new GzipCompress(); + compressArray[Options.CompressType.COMPRESS_TYPE_ZLIB_VALUE] = new ZlibCompress(); + compressArray[Options.CompressType.COMPRESS_TYPE_SNAPPY_VALUE] = new SnappyCompress(); + compressNum = 4; + } + + public Compress getCompress(int compressType) { + if (compressType < 0 || compressType >= compressNum) { + throw new RuntimeException("out of bound"); + } + Compress compress = compressArray[compressType]; + if (compress == null) { + String errMsg = String.format("compress type=%d not support", compressType); + log.warn(errMsg); + throw new RuntimeException(errMsg); + } + return compress; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/GzipCompress.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/GzipCompress.java new file mode 100644 index 00000000..a9b5f9b9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/GzipCompress.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.google.protobuf.CodedOutputStream; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.buffer.DynamicCompositeByteBufInputStream; +import com.baidu.brpc.utils.IOUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +@Slf4j +public class GzipCompress implements Compress { + @Override + public ByteBuf compressInput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + int protoSize = rpcMethodInfo.getInputSerializedSize(proto); + ByteBuf resBuf = Unpooled.buffer(protoSize); + OutputStream outputStream = new ByteBufOutputStream(resBuf); + GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream); + + if (protoSize > CodedOutputStream.DEFAULT_BUFFER_SIZE) { + protoSize = CodedOutputStream.DEFAULT_BUFFER_SIZE; + } + final CodedOutputStream codedOutputStream = + CodedOutputStream.newInstance(gzipOutputStream, protoSize); + rpcMethodInfo.inputWriteToStream(proto, codedOutputStream); + gzipOutputStream.close(); + return resBuf; + } + + @Override + public Object uncompressOutput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressOutput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressOutput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressInput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressInput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + public Object uncompressInput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new GZIPInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public ByteBuf compressOutput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + int protoSize = rpcMethodInfo.getOutputSerializedSize(proto); + ByteBuf resBuf = Unpooled.buffer(protoSize); + OutputStream outputStream = new ByteBufOutputStream(resBuf); + outputStream = new GZIPOutputStream(outputStream); + + if (protoSize > CodedOutputStream.DEFAULT_BUFFER_SIZE) { + protoSize = CodedOutputStream.DEFAULT_BUFFER_SIZE; + } + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream, protoSize); + rpcMethodInfo.outputWriteToStream(proto, codedOutputStream); + outputStream.close(); + return resBuf; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/NoneCompress.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/NoneCompress.java new file mode 100644 index 00000000..2db28d03 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/NoneCompress.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class NoneCompress implements Compress { + @Override + public ByteBuf compressInput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + byte[] bytes = rpcMethodInfo.inputEncode(proto); + return Unpooled.wrappedBuffer(bytes); + } + + @Override + public Object uncompressOutput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.outputDecode(byteBuf); + } + + @Override + public Object uncompressOutput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.outputDecode(bytes); + } + + @Override + public Object uncompressOutput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.outputDecode(byteBuf); + } + + @Override + public ByteBuf compressOutput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + byte[] bytes = rpcMethodInfo.outputEncode(proto); + return Unpooled.wrappedBuffer(bytes); + } + + @Override + public Object uncompressInput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.inputDecode(byteBuf); + } + + @Override + public Object uncompressInput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.inputDecode(bytes); + } + + @Override + public Object uncompressInput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + return rpcMethodInfo.inputDecode(byteBuf); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/SnappyCompress.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/SnappyCompress.java new file mode 100644 index 00000000..d0c85009 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/SnappyCompress.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.google.protobuf.Message; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.buffer.DynamicCompositeByteBufInputStream; +import com.baidu.brpc.utils.IOUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import org.xerial.snappy.Snappy; +import org.xerial.snappy.SnappyInputStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +@Slf4j +public class SnappyCompress implements Compress { + @Override + public ByteBuf compressInput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + byte[] bytes = rpcMethodInfo.inputEncode(proto); + int maxCompressedSize = Snappy.maxCompressedLength(bytes.length); + byte[] compressedBytes = new byte[maxCompressedSize]; + int compressedLen = Snappy.compress(bytes, 0, bytes.length, compressedBytes, 0); + return Unpooled.wrappedBuffer(compressedBytes, 0, compressedLen); + } + + @Override + public Object uncompressOutput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ProtobufRpcMethodInfo protobufRpcMethodInfo = (ProtobufRpcMethodInfo) rpcMethodInfo; + Message proto = (Message) protobufRpcMethodInfo.outputDecode(inputStream); + return proto; + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } + + @Override + public Object uncompressOutput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ProtobufRpcMethodInfo protobufRpcMethodInfo = (ProtobufRpcMethodInfo) rpcMethodInfo; + Message proto = (Message) protobufRpcMethodInfo.outputDecode(inputStream); + return proto; + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } + + @Override + public Object uncompressOutput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ProtobufRpcMethodInfo protobufRpcMethodInfo = (ProtobufRpcMethodInfo) rpcMethodInfo; + Message proto = (Message) protobufRpcMethodInfo.outputDecode(inputStream); + return proto; + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } + + @Override + public Object uncompressInput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } + + @Override + public Object uncompressInput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } + + @Override + public Object uncompressInput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new SnappyInputStream(inputStream); + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } + + @Override + public ByteBuf compressOutput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + byte[] bytes = rpcMethodInfo.outputEncode(proto); + int maxCompressedSize = Snappy.maxCompressedLength(bytes.length); + byte[] compressedBytes = new byte[maxCompressedSize]; + int compressedLen = Snappy.compress(bytes, 0, bytes.length, compressedBytes, 0); + return Unpooled.wrappedBuffer(compressedBytes, 0, compressedLen); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/compress/ZlibCompress.java b/brpc-java-core/src/main/java/com/baidu/brpc/compress/ZlibCompress.java new file mode 100644 index 00000000..6da3268f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/compress/ZlibCompress.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.google.protobuf.CodedOutputStream; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.buffer.DynamicCompositeByteBufInputStream; +import com.baidu.brpc.utils.IOUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +@Slf4j +public class ZlibCompress implements Compress { + @Override + public ByteBuf compressInput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + int protoSize = rpcMethodInfo.getInputSerializedSize(proto); + ByteBuf resBuf = Unpooled.buffer(protoSize); + OutputStream outputStream = new ByteBufOutputStream(resBuf); + outputStream = new DeflaterOutputStream(outputStream); + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream, protoSize); + rpcMethodInfo.inputWriteToStream(proto, codedOutputStream); + outputStream.close(); + return resBuf; + } + + @Override + public Object uncompressOutput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressOutput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressOutput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).outputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.outputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressInput(ByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteBufInputStream(byteBuf); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressInput(byte[] bytes, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new ByteArrayInputStream(bytes); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public Object uncompressInput(DynamicCompositeByteBuf byteBuf, RpcMethodInfo rpcMethodInfo) throws IOException { + InputStream inputStream = new DynamicCompositeByteBufInputStream(byteBuf); + inputStream = new InflaterInputStream(inputStream); + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + return ((ProtobufRpcMethodInfo) rpcMethodInfo).inputDecode(inputStream); + } else { + byte[] uncompressedBytes = IOUtils.readInputStream(inputStream); + return rpcMethodInfo.inputDecode(uncompressedBytes); + } + } finally { + inputStream.close(); + } + } + + @Override + public ByteBuf compressOutput(Object proto, RpcMethodInfo rpcMethodInfo) throws IOException { + int protoSize = rpcMethodInfo.getOutputSerializedSize(proto); + ByteBuf resBuf = Unpooled.buffer(protoSize); + OutputStream outputStream = new ByteBufOutputStream(resBuf); + outputStream = new DeflaterOutputStream(outputStream); + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream, protoSize); + rpcMethodInfo.outputWriteToStream(proto, codedOutputStream); + outputStream.close(); + return resBuf; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/BadSchemaException.java b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/BadSchemaException.java new file mode 100644 index 00000000..d9c77d1c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/BadSchemaException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.exceptions; + +public class BadSchemaException extends Exception { + private int code; + + public BadSchemaException() { + super(); + } + + public BadSchemaException(String message, Throwable cause) { + super(message, cause); + } + + public BadSchemaException(String message) { + super(message); + } + + public BadSchemaException(Throwable cause) { + super(cause); + } + + public BadSchemaException(int code) { + super(); + this.code = code; + } + + public BadSchemaException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public BadSchemaException(int code, String message) { + super(message); + this.code = code; + } + + public BadSchemaException(int code, Throwable cause) { + super(cause); + this.code = code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/NotEnoughDataException.java b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/NotEnoughDataException.java new file mode 100644 index 00000000..5826d479 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/NotEnoughDataException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.exceptions; + +public class NotEnoughDataException extends Exception { + private int code; + + public NotEnoughDataException() { + super(); + } + + public NotEnoughDataException(String message, Throwable cause) { + super(message, cause); + } + + public NotEnoughDataException(String message) { + super(message); + } + + public NotEnoughDataException(Throwable cause) { + super(cause); + } + + public NotEnoughDataException(int code) { + super(); + this.code = code; + } + + public NotEnoughDataException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public NotEnoughDataException(int code, String message) { + super(message); + this.code = code; + } + + public NotEnoughDataException(int code, Throwable cause) { + super(cause); + this.code = code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/RpcException.java b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/RpcException.java new file mode 100644 index 00000000..0fe3d63d --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/RpcException.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.exceptions; + +public class RpcException extends RuntimeException { + public static final int UNKNOWN_EXCEPTION = 0; + public static final int NETWORK_EXCEPTION = 1; + public static final int TIMEOUT_EXCEPTION = 2; + public static final int SERVICE_EXCEPTION = 3; + public static final int FORBIDDEN_EXCEPTION = 4; + public static final int SERIALIZATION_EXCEPTION = 5; + public static final int INTERCEPT_EXCEPTION = 6; + private static final long serialVersionUID = 7815426523583648235L; + private int code; + + public RpcException() { + super(); + } + + public RpcException(String message, Throwable cause) { + super(message, cause); + } + + public RpcException(String message) { + super(message); + } + + public RpcException(Throwable cause) { + super(cause); + } + + public RpcException(int code) { + super(); + this.code = code; + } + + public RpcException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public RpcException(int code, String message) { + super(message); + this.code = code; + } + + public RpcException(int code, Throwable cause) { + super(cause); + this.code = code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public boolean isServiceException() { + return code == SERVICE_EXCEPTION; + } + + public boolean isForbidded() { + return code == FORBIDDEN_EXCEPTION; + } + + public boolean isTimeout() { + return code == TIMEOUT_EXCEPTION; + } + + public boolean isNetwork() { + return code == NETWORK_EXCEPTION; + } + + public boolean isSerialization() { + return code == SERIALIZATION_EXCEPTION; + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/TooBigDataException.java b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/TooBigDataException.java new file mode 100644 index 00000000..9067088c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/exceptions/TooBigDataException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.exceptions; + +public class TooBigDataException extends Exception { + private int code; + + public TooBigDataException() { + super(); + } + + public TooBigDataException(String message, Throwable cause) { + super(message, cause); + } + + public TooBigDataException(String message) { + super(message); + } + + public TooBigDataException(Throwable cause) { + super(cause); + } + + public TooBigDataException(int code) { + super(); + this.code = code; + } + + public TooBigDataException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public TooBigDataException(int code, String message) { + super(message); + this.code = code; + } + + public TooBigDataException(int code, Throwable cause) { + super(cause); + this.code = code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/AbstractInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/AbstractInterceptor.java new file mode 100644 index 00000000..d2cf0278 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/AbstractInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +public abstract class AbstractInterceptor implements Interceptor { + + @Override + public boolean handleRequest(Request request) { + return true; + } + + @Override + public void handleResponse(Response response) { + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + chain.intercept(request, response); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ClientTraceInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ClientTraceInterceptor.java new file mode 100644 index 00000000..4acd0790 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ClientTraceInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +/** + * Interceptor for client side tracing. + *

+ * This interceptor is just a placeholder for integration with tracing tools using AOP. + */ +public class ClientTraceInterceptor extends AbstractInterceptor { + @Override + public boolean handleRequest(Request request) { + return super.handleRequest(request); + } + + @Override + public void handleResponse(Response response) { + super.handleResponse(response); + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + super.aroundProcess(request, response, chain); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/CurrentLimitInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/CurrentLimitInterceptor.java new file mode 100644 index 00000000..05e985b1 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/CurrentLimitInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.server.currentlimit.CurrentLimiter; + +/** + * Rpc server current limit interceptor + * Specific current limiting algorithm leaves to the {@link CurrentLimiter} + * + * @author wangjiayin@baidu.com + * @since 2018/11/26 + */ +public class CurrentLimitInterceptor extends AbstractInterceptor { + + private CurrentLimiter limiter; + + public CurrentLimitInterceptor(CurrentLimiter limiter) { + this.limiter = limiter; + } + + @Override + public boolean handleRequest(Request request) { + return limiter.isAllowable(request); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/DefaultInterceptorChain.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/DefaultInterceptorChain.java new file mode 100644 index 00000000..9c2de52f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/DefaultInterceptorChain.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import java.util.Iterator; +import java.util.List; + +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +public class DefaultInterceptorChain implements InterceptorChain { + private List interceptors; + private Iterator iterator; + + public DefaultInterceptorChain(List interceptors) { + this.interceptors = interceptors; + this.iterator = interceptors.iterator(); + } + + @Override + public void intercept(Request request, Response response) throws Exception { + if (iterator.hasNext()) { + Interceptor interceptor = iterator.next(); + boolean success = interceptor.handleRequest(request); + if (!success) { + throw new RpcException(RpcException.INTERCEPT_EXCEPTION, "request intercept fail"); + } + interceptor.aroundProcess(request, response, this); + if (request.getCallback() == null) { + interceptor.handleResponse(response); + } + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/Interceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/Interceptor.java new file mode 100755 index 00000000..fc898dc4 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/Interceptor.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +/** + * The client or server intercepts the interface. + * The reason for dividing the two functions is that in the asynchronous scenario, + * the request and response cannot be obtained at the same time. + * @author Li Yuanxin(liyuanxin@baidu.com) + */ +public interface Interceptor { + /** + * This method is called in two scenarios: + * Before the client sends the request; + * Before the server processes the request. + * @param request request content, when the business is implemented, it needs to be converted into the type + * required by the specific protocol. + * @return True means continue execution, false means stop execution and return + */ + boolean handleRequest(Request request); + + /** + * This method is called in two scenarios: + * Before the server sends the response; + * After the client receives the response. + * @param response server response content, when the business is implemented, it needs to be converted into the type + */ + void handleResponse(Response response); + + /** + * The around intercept for RPC methods. + * Attention: only around the request sending for async client + * @param chain interceptor chain + * @param response sync result or async future + * @param chain the interceptor call chain + */ + void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/InterceptorChain.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/InterceptorChain.java new file mode 100644 index 00000000..548fd046 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/InterceptorChain.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +public interface InterceptorChain { + void intercept(Request request, Response response) throws Exception; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/LoadBalanceInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/LoadBalanceInterceptor.java new file mode 100644 index 00000000..d17507b1 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/LoadBalanceInterceptor.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import lombok.Setter; + +import java.util.HashSet; +import java.util.concurrent.TimeUnit; + +/** + * retry + load balance + rpc. + * this interceptor is the last one of client interceptor list. + * user can implement custom interceptor to replace it. + */ + +@Setter +public class LoadBalanceInterceptor extends AbstractInterceptor { + protected RpcClient rpcClient; + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + RpcException exception = null; + int currentTryTimes = 0; + int maxTryTimes = rpcClient.getRpcClientOptions().getMaxTryTimes(); + while (currentTryTimes < maxTryTimes) { + try { + // if it is a retry request, add the last selected instance to request, + // so that load balance strategy can exclude the selected instance. + // if it is the initial request, not init HashSet, so it is more fast. + // therefore, it need LoadBalanceStrategy to judge if selectInstances is null. + if (currentTryTimes > 0) { + if (request.getChannel() != null) { + if (request.getSelectedInstances() == null) { + request.setSelectedInstances(new HashSet(maxTryTimes - 1)); + } + BrpcChannel lastInstance = ChannelInfo + .getClientChannelInfo(request.getChannel()).getChannelGroup(); + request.getSelectedInstances().add(lastInstance); + } + } + invokeRpc(request, response); + break; + } catch (RpcException ex) { + exception = ex; + if (exception.getCode() == RpcException.INTERCEPT_EXCEPTION) { + break; + } + } finally { + currentTryTimes++; + } + } + if (response.getResult() == null && response.getRpcFuture() == null) { + if (exception == null) { + exception = new RpcException(RpcException.UNKNOWN_EXCEPTION, "unknown error"); + } + response.setException(exception); + } + } + + protected void invokeRpc(Request request, Response response) throws Exception { + rpcCore(request, response); + } + + + protected void rpcCore(Request request, Response response) throws Exception { + // send request with the channel. + RpcFuture future = (RpcFuture) rpcClient.sendRequest(request); + // receive + if (future.isAsync()) { + response.setRpcFuture(future); + } else { + response.setResult(future.get(request.getReadTimeoutMillis(), TimeUnit.MILLISECONDS)); + response.setCorrelationId(future.getCorrelationId()); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerInvokeInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerInvokeInterceptor.java new file mode 100644 index 00000000..d2e4a921 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerInvokeInterceptor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.InvocationTargetException; + +@Slf4j +public class ServerInvokeInterceptor extends AbstractInterceptor { + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + try { + response.setResult(request.getTargetMethod().invoke(request.getTarget(), request.getArgs())); + } catch (InvocationTargetException ex) { + Throwable targetException = ex.getTargetException(); + if (targetException == null) { + targetException = ex; + } + String errorMsg = String.format("invoke method failed, msg=%s", targetException.getMessage()); + log.warn(errorMsg, targetException); + response.setException(targetException); + } catch (Throwable ex) { + String errorMsg = String.format("invoke method failed, msg=%s", ex.getMessage()); + log.warn(errorMsg, ex); + response.setException(ex); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerPushInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerPushInterceptor.java new file mode 100644 index 00000000..306f3dd5 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerPushInterceptor.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ + +package com.baidu.brpc.interceptor; + +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.client.AsyncAwareFuture; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.server.ChannelManager; +import com.baidu.brpc.server.RpcServer; + +import io.netty.channel.Channel; +import lombok.Setter; + +/** + * retry + load balance + rpc. + * this interceptor is the last one of client interceptor list. + * user can implement custom interceptor to replace it. + */ +@Setter +public class ServerPushInterceptor extends AbstractInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(ServerPushInterceptor.class); + + protected RpcServer rpcServer; + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + RpcException exception = null; + int currentTryTimes = 0; + int maxTryTimes = rpcServer.getRpcServerOptions().getMaxTryTimes(); + while (currentTryTimes < maxTryTimes) { + try { + + // if (currentTryTimes > 0) { + // if (request.getChannel() != null) { + // if (request.getSelectedInstances() == null) { + // request.setSelectedInstances(new HashSet(maxTryTimes - + // 1)); + // } + // BrpcChannel lastInstance = ChannelInfo + // .getClientChannelInfo(request.getChannel()).getChannelGroup(); + // request.getSelectedInstances().add(lastInstance); + // } + // } + invokeRpc(request, response); + break; + } catch (RpcException ex) { + exception = ex; + if (exception.getCode() == RpcException.INTERCEPT_EXCEPTION) { + break; + } + } finally { + currentTryTimes++; + } + } + if (response.getResult() == null && response.getRpcFuture() == null) { + if (exception == null) { + exception = new RpcException(RpcException.UNKNOWN_EXCEPTION, "unknown error"); + } + response.setException(exception); + } + } + + protected void invokeRpc(Request request, Response response) throws Exception { + selectChannel(request); + rpcCore(request, response); + } + + protected Channel selectChannel(Request request) { + // select instance by server push + ChannelManager channelManager = ChannelManager.getInstance(); + String clientName = request.getClientName(); + Channel channel = channelManager.getChannel(clientName); + if (channel == null) { + LOG.error("cannot find a valid channel by name:" + clientName); + throw new RpcException("cannot find a valid channel by name:" + clientName); + } + request.setChannel(channel); + return channel; + } + + protected void rpcCore(Request request, Response response) throws Exception { + // send request with the channel. + AsyncAwareFuture future = rpcServer.sendServerPush(request); + if (future.isAsync()) { + response.setRpcFuture((RpcFuture) future); + } else { + response.setResult(future.get(request.getReadTimeoutMillis(), TimeUnit.MILLISECONDS)); + } + } + + public RpcServer getRpcServer() { + return rpcServer; + } + + public void setRpcServer(RpcServer rpcServer) { + this.rpcServer = rpcServer; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerTraceInterceptor.java b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerTraceInterceptor.java new file mode 100644 index 00000000..0986f964 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/interceptor/ServerTraceInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +/** + * Interceptor for server side tracing. + *

+ * This interceptor is just a placeholder for integration with tracing tools using AOP. + */ +public class ServerTraceInterceptor extends AbstractInterceptor { + @Override + public boolean handleRequest(Request request) { + return super.handleRequest(request); + } + + @Override + public void handleResponse(Response response) { + super.handleResponse(response); + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + super.aroundProcess(request, response, chain); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/BrpcURL.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/BrpcURL.java new file mode 100644 index 00000000..cfae91b6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/BrpcURL.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * format is "list://127.0.0.1:8002,127.0.0.1:8003/path?key1=value1&key2=value2" + */ +@Setter +@Getter +@Slf4j +public class BrpcURL { + private String schema; + /** + * we do not parse host and port, + * because different naming url has different formats: + * "127.0.0.1:8002,127.0.0.1:8003" + * "test.bj:portTag" + * "brpc.com" + * "127.0.0.1:8080" + */ + private String hostPorts; + private String path; + private Map queryMap = new HashMap(); + + public BrpcURL(String uri) { + // schema + int index = uri.indexOf("://"); + if (index < 0) { + throw new IllegalArgumentException("invalid uri:" + uri); + } + this.schema = uri.substring(0, index).toLowerCase(); + // hostPorts + int index2 = uri.indexOf('/', index + 3); + int index3 = uri.indexOf('?', index + 3); + if (index2 > 0) { + this.hostPorts = uri.substring(index + 3, index2); + } else if (index3 > 0) { + this.hostPorts = uri.substring(index + 3, index3); + } else { + this.hostPorts = uri.substring(index + 3); + } + + // path + if (index2 > 0) { + if (index3 > 0) { + this.path = uri.substring(index2, index3); + } else { + this.path = uri.substring(index2); + } + } else { + this.path = "/"; + } + + // query + if (index3 > 0) { + String query = uri.substring(index3 + 1); + String[] querySplits = query.split("&"); + for (String kv : querySplits) { + String[] kvSplit = kv.split("="); + queryMap.put(kvSplit[0], kvSplit[1]); + } + } + } + + public void addParameter(String key, Object value) { + queryMap.put(key, value); + } + + public Object getParameter(String key) { + return queryMap.get(key); + } + + public Object getParameter(String key, Object defaultValue) { + Object value = queryMap.get(key); + if (value == null) { + value = defaultValue; + } + return value; + } + + public int getIntParameter(String key, int defaultValue) { + Object value = queryMap.get(key); + if (value != null) { + return Integer.valueOf((String) value); + } else { + return defaultValue; + } + } + + public String getStringParameter(String key, String defaultValue) { + Object value = queryMap.get(key); + if (value != null) { + return (String) value; + } else { + return defaultValue; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(schema).append("://"); + if (StringUtils.isNotBlank(hostPorts)) { + sb.append(hostPorts); + } + sb.append(path); + if (queryMap.size() > 0) { + sb.append("?"); + for (Map.Entry entry : queryMap.entrySet()) { + sb.append(entry.getKey()).append("=").append(entry.getValue()); + } + } + return sb.toString(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/Constants.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/Constants.java new file mode 100644 index 00000000..88be7523 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/Constants.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +public class Constants { + public static final String GROUP = "group"; + public static final String VERSION = "version"; + + // update timer interval for pull mode + public static final String INTERVAL = "interval"; + public static final int DEFAULT_INTERVAL = 5000; + + public static final String SLEEP_TIME_MS = "sleepTimeMs"; + public static final int DEFAULT_SLEEP_TIME_MS = 1000; + + public static final String MAX_TRY_TIMES = "maxTryTimes"; + public static final int DEFAULT_MAX_TRY_TIMES = 3; + + public static final String CONNECT_TIMEOUT_MS = "connectTimeoutMs"; + public static final int DEFAULT_CONNECT_TIMEOUT_MS = 1000; + + public static final String SESSION_TIMEOUT_MS = "sessionTimeoutMs"; + public static final int DEFAULT_SESSION_TIMEOUT_MS = 60000; + + public static final String DEFAULT_PATH = ""; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingService.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingService.java new file mode 100644 index 00000000..80a90626 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingService.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.Validate; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; + +public class DnsNamingService implements NamingService { + private BrpcURL namingUrl; + private String host; + private int port; + private String hostPort; + private List lastInstances = new ArrayList(); + private Timer namingServiceTimer; + private int updateInterval; + + public DnsNamingService(BrpcURL namingUrl) { + Validate.notNull(namingUrl); + Validate.notEmpty(namingUrl.getHostPorts()); + this.namingUrl = namingUrl; + + String[] splits = namingUrl.getHostPorts().split(":"); + this.host = splits[0]; + if (splits.length == 2) { + this.port = Integer.valueOf(splits[1]); + } else { + this.port = 80; + } + this.hostPort = this.host + ":" + this.port; + this.updateInterval = namingUrl.getIntParameter( + Constants.INTERVAL, Constants.DEFAULT_INTERVAL); + namingServiceTimer = new HashedWheelTimer(new CustomThreadFactory("namingService-timer-thread")); + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + InetAddress[] addresses; + try { + addresses = InetAddress.getAllByName(host); + } catch (UnknownHostException ex) { + throw new IllegalArgumentException("unknown http host"); + } + + List instances = new ArrayList(); + for (InetAddress address : addresses) { + ServiceInstance instance = new ServiceInstance(address.getHostAddress(), port); + instances.add(instance); + } + return instances; + } + + @Override + public void subscribe(SubscribeInfo subscribeInfo, final NotifyListener listener) { + namingServiceTimer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + try { + List currentInstances = lookup(null); + Collection addList = CollectionUtils.subtract( + currentInstances, lastInstances); + Collection deleteList = CollectionUtils.subtract( + lastInstances, currentInstances); + listener.notify(addList, deleteList); + lastInstances = currentInstances; + } catch (Exception ex) { + // ignore exception + } + namingServiceTimer.newTimeout(this, updateInterval, TimeUnit.MILLISECONDS); + + } + }, + updateInterval, TimeUnit.MILLISECONDS); + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + namingServiceTimer.stop(); + } + + @Override + public void register(RegisterInfo registerInfo) { + } + + @Override + public void unregister(RegisterInfo registerInfo) { + } + + public String getHostPort() { + return hostPort; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingServiceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingServiceFactory.java new file mode 100644 index 00000000..9331394c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/DnsNamingServiceFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +public class DnsNamingServiceFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "dns"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + String schema = url.getSchema(); + if ("dns".equals(schema)) { + return new DnsNamingService(url); + } else { + throw new IllegalArgumentException("schema is not valid:" + schema); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingService.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingService.java new file mode 100644 index 00000000..001163ad --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingService.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; + +/** + * Fetch service list from File Naming Service + */ +public class FileNamingService implements NamingService { + private static final Logger LOG = LoggerFactory.getLogger(FileNamingService.class); + private BrpcURL namingUrl; + private String filePath; + private List lastInstances = new ArrayList(); + private Timer namingServiceTimer; + private long lastModified; + private int updateInterval; + + public FileNamingService(BrpcURL namingUrl) { + Validate.notNull(namingUrl); + Validate.notNull(namingUrl.getPath()); + this.namingUrl = namingUrl; + this.filePath = namingUrl.getPath(); + this.updateInterval = namingUrl.getIntParameter( + Constants.INTERVAL, Constants.DEFAULT_INTERVAL); + namingServiceTimer = new HashedWheelTimer(new CustomThreadFactory("namingService-timer-thread")); + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + List list = new ArrayList(); + int lineNum = 0; + BufferedReader reader = null; + try { + File file = new File(filePath); + long lastModified = file.lastModified(); + reader = new BufferedReader(new FileReader(file)); + String line; + while ((line = reader.readLine()) != null) { + lineNum++; + line = line.trim(); + String[] ipPort = line.split(":"); + if (ipPort.length != 2) { + LOG.warn("Invalid address format: " + line); + continue; + } + ServiceInstance instance = new ServiceInstance(ipPort[0].trim(), + Integer.valueOf(ipPort[1].trim())); + list.add(instance); + } + LOG.debug("Got " + list.size() + " servers (out of " + lineNum + ')' + + " from " + filePath); + this.lastModified = lastModified; + return list; + } catch (IOException ex) { + LOG.warn("read file error, fileName={}", filePath); + throw new RuntimeException("read naming file error"); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex2) { + LOG.warn("close failed"); + } + } + } + } + + @Override + public void subscribe(SubscribeInfo subscribeInfo, final NotifyListener listener) { + namingServiceTimer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + try { + File file = new File(filePath); + long currentModified = file.lastModified(); + if (currentModified > lastModified) { + List currentInstances = lookup(null); + Collection addList = CollectionUtils.subtract( + currentInstances, lastInstances); + Collection deleteList = CollectionUtils.subtract( + lastInstances, currentInstances); + listener.notify(addList, deleteList); + lastInstances = currentInstances; + } + } catch (Exception ex) { + // ignore exception + } + namingServiceTimer.newTimeout(this, updateInterval, TimeUnit.MILLISECONDS); + + } + }, + updateInterval, TimeUnit.MILLISECONDS); + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + namingServiceTimer.stop(); + } + + @Override + public void register(RegisterInfo registerInfo) { + } + + @Override + public void unregister(RegisterInfo registerInfo) { + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingServiceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingServiceFactory.java new file mode 100644 index 00000000..8152e759 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/FileNamingServiceFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +public class FileNamingServiceFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "file"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + String schema = url.getSchema(); + if ("file".equals(schema)) { + return new FileNamingService(url); + } else { + throw new IllegalArgumentException("schema is not valid:" + schema); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingService.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingService.java new file mode 100644 index 00000000..f510fb78 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingService.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.Validate; + +import com.baidu.brpc.client.instance.ServiceInstance; + +/** + * Fetch service list from List Naming Service + */ +public class ListNamingService implements NamingService { + private List instances; + + public ListNamingService(BrpcURL namingUrl) { + Validate.notNull(namingUrl); + Validate.notEmpty(namingUrl.getHostPorts()); + + String hostPorts = namingUrl.getHostPorts(); + String[] hostPortSplits = hostPorts.split(","); + this.instances = new ArrayList(hostPortSplits.length); + for (String hostPort : hostPortSplits) { + String[] hostPortSplit = hostPort.split(":"); + String host = hostPortSplit[0]; + int port; + if (hostPortSplit.length == 2) { + port = Integer.valueOf(hostPortSplit[1]); + } else { + port = 80; + } + instances.add(new ServiceInstance(host, port)); + } + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + return instances; + } + + @Override + public void subscribe(SubscribeInfo subscribeInfo, final NotifyListener listener) { + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + } + + @Override + public void register(RegisterInfo registerInfo) { + } + + @Override + public void unregister(RegisterInfo registerInfo) { + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingServiceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingServiceFactory.java new file mode 100644 index 00000000..e291c8bb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/ListNamingServiceFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +public class ListNamingServiceFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "list"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + String schema = url.getSchema(); + if ("list".equals(schema)) { + return new ListNamingService(url); + } else { + throw new IllegalArgumentException("schema is not valid:" + schema); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingOptions.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingOptions.java new file mode 100644 index 00000000..3ce744cd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingOptions.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Setter +@Getter +public class NamingOptions { + /** + * identify different service implementation for the same interface. + */ + private String group = "normal"; + + /** + * identify service version. + */ + private String version = "1.0.0"; + + /** + * if true, naming service will throw exception when register/subscribe exceptions. + */ + private boolean ignoreFailOfNamingService = false; + + /** + * use serviceId to identify all instances for this service. + */ + private String serviceId = ""; + + /** + * extra {@link NamingService} specific options + */ + private Map extra; + + public NamingOptions() { + } + + public NamingOptions(NamingOptions rhs) { + this.group = rhs.getGroup(); + this.version = rhs.getVersion(); + this.ignoreFailOfNamingService = rhs.isIgnoreFailOfNamingService(); + this.serviceId = rhs.getServiceId(); + this.extra = rhs.extra; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingService.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingService.java new file mode 100644 index 00000000..d217ccee --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingService.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.util.List; + +import com.baidu.brpc.client.instance.ServiceInstance; + +public interface NamingService { + /** + * 查询符合条件的已注册数据,与订阅的推模式相对应,这里为拉模式,只返回一次结果。 + * + * @param subscribeInfo service/group/version info + * @return 已注册信息列表,可能为空。 + */ + List lookup(SubscribeInfo subscribeInfo); + + /** + * 订阅符合条件的已注册数据,当有注册数据变更时自动推送. + * + * @param listener 变更事件监听器,不允许为空 + */ + void subscribe(SubscribeInfo subscribeInfo, NotifyListener listener); + + /** + * 取消订阅. + * + */ + void unsubscribe(SubscribeInfo subscribeInfo); + + /** + * 注册数据,比如:提供者地址,消费者地址,路由规则,覆盖规则,等数据。 + * + * @param registerInfo service/group/version info + */ + void register(RegisterInfo registerInfo); + + /** + * 取消注册. + * + * @param registerInfo service/group/version info + */ + void unregister(RegisterInfo registerInfo); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactory.java new file mode 100644 index 00000000..eb52736d --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactory.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +public interface NamingServiceFactory { + String getName(); + NamingService createNamingService(BrpcURL url); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactoryManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactoryManager.java new file mode 100644 index 00000000..0d808ee2 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NamingServiceFactoryManager.java @@ -0,0 +1,44 @@ +package com.baidu.brpc.naming; + +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class NamingServiceFactoryManager { + private static volatile NamingServiceFactoryManager instance; + + private Map namingServiceFactoryMap; + + public static NamingServiceFactoryManager getInstance() { + if (instance == null) { + synchronized (NamingServiceFactoryManager.class) { + if (instance == null) { + instance = new NamingServiceFactoryManager(); + } + } + } + return instance; + } + + private NamingServiceFactoryManager() { + this.namingServiceFactoryMap = new HashMap(); + this.namingServiceFactoryMap.put("list", new ListNamingServiceFactory()); + this.namingServiceFactoryMap.put("file", new FileNamingServiceFactory()); + this.namingServiceFactoryMap.put("dns", new DnsNamingServiceFactory()); + } + + public void registerNamingServiceFactory(NamingServiceFactory namingServiceFactory) { + if (namingServiceFactoryMap.get(namingServiceFactory.getName()) != null) { + throw new RuntimeException("naming service exist:" + namingServiceFactory.getName()); + } + namingServiceFactoryMap.put(namingServiceFactory.getName(), namingServiceFactory); + log.info("register naming service:{} success", namingServiceFactory.getName()); + } + + public NamingServiceFactory getNamingServiceFactory(String name) { + return namingServiceFactoryMap.get(name); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/NotifyListener.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NotifyListener.java new file mode 100644 index 00000000..ab251f72 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/NotifyListener.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import java.util.Collection; + +import com.baidu.brpc.client.instance.ServiceInstance; + +/** + * NotifyListener. (API, Prototype, ThreadSafe) + * + * @author xiemalin + * @since 2.27 + */ +public interface NotifyListener { + + /** + * 当收到服务变更通知时触发。 + * + * @param addList to be added endpoints + * @param deleteList to be deleted endpoints + */ + void notify(Collection addList, Collection deleteList); +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/RegisterInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/RegisterInfo.java new file mode 100644 index 00000000..d94f89d8 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/RegisterInfo.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * POJO class of register info. + * + * @author xiemalin + */ +@Setter +@Getter +@EqualsAndHashCode +public class RegisterInfo extends NamingOptions { + + private String host; + + private int port; + + /** + * the interface class name. + */ + private String interfaceName; + + public RegisterInfo() { + } + + public RegisterInfo(RegisterInfo rhs) { + super(rhs); + this.host = rhs.getHost(); + this.port = rhs.getPort(); + this.interfaceName = rhs.getInterfaceName(); + } + + public RegisterInfo(NamingOptions namingOptions) { + super(namingOptions); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/naming/SubscribeInfo.java b/brpc-java-core/src/main/java/com/baidu/brpc/naming/SubscribeInfo.java new file mode 100644 index 00000000..9722a34b --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/naming/SubscribeInfo.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * POJO class of subscribe info. + * + * @author xiemalin + */ +@Setter +@Getter +@EqualsAndHashCode +public class SubscribeInfo extends NamingOptions { + /** + * the interface class name. + */ + private String interfaceName; + + public SubscribeInfo() { + } + + public SubscribeInfo(SubscribeInfo rhs) { + super(rhs); + this.interfaceName = rhs.getInterfaceName(); + } + + public SubscribeInfo(NamingOptions namingOptions) { + super(namingOptions); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractProtocol.java new file mode 100644 index 00000000..332545ef --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractProtocol.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.NotEnoughDataException; + +import io.netty.channel.ChannelFuture; + +/** + * An abstract protocol used to simplify tcp protocol implementations. + * Http protocol implementations extended this class need to override most methods, + * or implements {@link Protocol} interface directly. + */ +public abstract class AbstractProtocol implements Protocol { + + protected static NotEnoughDataException notEnoughDataException = new NotEnoughDataException(); + + @Override + public Request createRequest() { + // tcp protocol implementation, http protocols should override this method + return new RpcRequest(); + } + + @Override + public Response createResponse() { + // tcp protocol implementation, http protocols should override this method + return new RpcResponse(); + } + + @Override + public Request getRequest() { + // tcp protocol implementation, http protocols should override this method + Request request = RpcRequest.getRpcRequest(); + request.reset(); + return request; + } + + @Override + public Response getResponse() { + // tcp protocol implementation, http protocols should override this method + Response response = RpcResponse.getRpcResponse(); + response.reset(); + return response; + } + + @Override + public void beforeRequestSent(Request request, RpcClient rpcClient, BrpcChannel channelGroup) { + // By default, in tcp protocols, there's nothing to to + } + + @Override + public boolean returnChannelBeforeResponse() { + return true; + } + + @Override + public void afterResponseSent(Request request, Response response, ChannelFuture channelFuture) { + // By default, in tcp protocols, there's nothing to to + } + + @Override + public boolean isCoexistence() { + return false; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractRequest.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractRequest.java new file mode 100644 index 00000000..af17efa0 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractRequest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.push.SPHead; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public abstract class AbstractRequest implements Request { + private Object msg; + // used to find RpcFuture, application can not set it. + private long correlationId; + // used to identify request for application, application can set it. + private long logId; + private Object target; + private Method targetMethod; + private RpcMethodInfo rpcMethodInfo; + private String serviceName; + private String methodName; + private Object[] args; + private NSHead nsHead; + private SPHead spHead; + private Map kvAttachment; + private ByteBuf binaryAttachment; + private int compressType; + private RpcException exception; + private Channel channel; + private Set selectedInstances; + private String auth; + private Long traceId; + private Long spanId; + private Long parentSpanId; + private RpcCallback callback; + private String serviceTag; + private Integer readTimeoutMillis; + private Integer writeTimeoutMillis; + private String clientName; + private boolean oneWay; // if false, do not need send response. + private RpcFuture rpcFuture; // just used by client + private ByteBuf sendBuf; // just used by client + + /** + * 订阅信息,客户端请求时,将订阅的服务信息存入 + * - Stargate使用 + */ + private SubscribeInfo subscribeInfo; + + @Override + public void reset() { + msg = null; + logId = -1; + target = null; + targetMethod = null; + rpcMethodInfo = null; + serviceName = null; + methodName = null; + args = null; + nsHead = null; + kvAttachment = null; + binaryAttachment = null; + compressType = 0; + exception = null; + channel = null; + selectedInstances = null; + traceId = null; + spanId = null; + parentSpanId = null; + callback = null; + serviceTag = null; + readTimeoutMillis = null; + writeTimeoutMillis = null; + oneWay = false; + rpcFuture = null; + sendBuf = null; + } + + @Override + public Request retain() { + if (binaryAttachment != null) { + binaryAttachment.retain(); + } + return this; + } + + @Override + public void release() { + if (binaryAttachment != null && binaryAttachment.refCnt() > 0) { + binaryAttachment.release(); + binaryAttachment = null; + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractResponse.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractResponse.java new file mode 100644 index 00000000..342286ab --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/AbstractResponse.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ +package com.baidu.brpc.protocol; + +import java.util.Map; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.push.SPHead; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public abstract class AbstractResponse implements Response { + // used to find RpcFuture, application can not set it. + private long correlationId; + // used to identify request for application, application can set it. + private long logId; + private Object result; + private Throwable exception; + private RpcMethodInfo rpcMethodInfo; + private RpcFuture rpcFuture; + private Map kvAttachment; + private ByteBuf binaryAttachment; + private int compressType; + private NSHead nsHead; + private SPHead spHead; + + public void reset() { + correlationId = -1; + logId = -1; + result = null; + exception = null; + rpcMethodInfo = null; + rpcFuture = null; + nsHead = null; + kvAttachment = null; + binaryAttachment = null; + compressType = 0; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/BrpcMeta.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/BrpcMeta.java new file mode 100644 index 00000000..2ab0e23e --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/BrpcMeta.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.Documented; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface BrpcMeta { + /** + * 发给服务端的服务名称,对于brpc标准协议,名称为proto文件中package后面的内容 + */ + String serviceName() default ""; + + /** + * 发给服务端的方法名称,对于brpc标准协议,名称为proto文件中service里的方法名 + */ + String methodName() default ""; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpRequest.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpRequest.java new file mode 100644 index 00000000..f1affb5b --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpRequest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.FastThreadLocal; +import lombok.Getter; +import lombok.Setter; + +/** + * Bprc http request implementation, used for http protocols. + * So far, we use netty {@link io.netty.handler.codec.http.HttpClientCodec} + * and {@link io.netty.handler.codec.http.HttpServerCodec} + * and {@link io.netty.handler.codec.http.HttpObjectAggregator} to handle http message. + * + * @author wangjiayin@baidu.com + * @see com.baidu.brpc.client.RpcClient + * @see com.baidu.brpc.server.RpcServer + * @since 2018-12-26 + */ +@Getter +@Setter +public class HttpRequest extends AbstractRequest { + + private static final FastThreadLocal CURRENT_RPC_REQUEST = new FastThreadLocal() { + @Override + protected HttpRequest initialValue() { + return new HttpRequest(); + } + }; + + public static HttpRequest getHttpRequest() { + return CURRENT_RPC_REQUEST.get(); + } + + private FullHttpRequest nettyHttpRequest; + + public HttpRequest() { + this.nettyHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, ""); + } + + @Override + public Object getMsg() { + return nettyHttpRequest; + } + + @Override + public void setMsg(Object o) { + FullHttpRequest request = (FullHttpRequest) o; + nettyHttpRequest.setProtocolVersion(request.protocolVersion()); + nettyHttpRequest.headers().add(request.headers()); + nettyHttpRequest.setMethod(request.method()); + nettyHttpRequest.setUri(request.uri()); + nettyHttpRequest.content().writeBytes(request.content()); + nettyHttpRequest.trailingHeaders().add(request.trailingHeaders()); + nettyHttpRequest.setDecoderResult(request.decoderResult()); + } + + @Override + public void reset() { + super.reset(); + nettyHttpRequest.setUri(""); + nettyHttpRequest.content().clear(); + nettyHttpRequest.headers().clear(); + nettyHttpRequest.trailingHeaders().clear(); + } + + @Override + public Request retain() { + super.retain(); + nettyHttpRequest.retain(); + return this; + } + + @Override + public void release() { + super.release(); + if (nettyHttpRequest.refCnt() > 0) { + nettyHttpRequest.release(); + } + } + + public HttpHeaders headers() { + return nettyHttpRequest.headers(); + } + + public String uri() { + return nettyHttpRequest.uri(); + } + + public ByteBuf content() { + return nettyHttpRequest.content(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpResponse.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpResponse.java new file mode 100644 index 00000000..7375c13d --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/HttpResponse.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol; + +import io.netty.util.concurrent.FastThreadLocal; + +/** + * Bprc http response implementation, used for http protocols. + * So far, we use netty {@link io.netty.handler.codec.http.HttpClientCodec} + * and {@link io.netty.handler.codec.http.HttpServerCodec} + * and {@link io.netty.handler.codec.http.HttpObjectAggregator} to handle http message. + * + * @author wangjiayin@baidu.com + * @see com.baidu.brpc.client.RpcClient + * @see com.baidu.brpc.server.RpcServer + * @since 2018-12-26 + */ +public class HttpResponse extends AbstractResponse { + + private static final FastThreadLocal CURRENT_RPC_RESPONSE = new FastThreadLocal() { + @Override + protected HttpResponse initialValue() { + return new HttpResponse(); + } + }; + + public static HttpResponse getHttpResponse() { + return CURRENT_RPC_RESPONSE.get(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Protocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Protocol.java new file mode 100644 index 00000000..2b56ad4b --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Protocol.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.TooBigDataException; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; + +/** + * rpc协议接口,业务如果想实现一个自定义协议,需要实现该接口。 + * Created by huwenwei on 2017/9/22. + */ +public interface Protocol { + + /**************** 客户端、服务端都要实现的函数。 *******************/ + + /** + * 客户端/服务端解析请求包成header+body buffer + * @param in 输入byte buf + * @return header+body buffer + * @throws BadSchemaException header格式不对 + * @throws TooBigDataException body太大 + * @throws NotEnoughDataException 可读长度不够,由于粘包拆包问题。 + */ + Object decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException; + + /** + * 该协议是否可以和其他协议共存。 + * @return true可以共存,false不能共存。 + */ + boolean isCoexistence(); + + /** + * create a new request instance + */ + Request createRequest(); + + /** + * create a new response instance + */ + Response createResponse(); + + /** + * get a reusable request instance from threadLocal or pool + * the request instance must be reset before reuse + */ + Request getRequest(); + + /** + * get a reusable response instance from threadLocal or pool + * the response instance must be reset before reuse + */ + Response getResponse(); + + /**************** 仅客户端需要实现的函数 *******************/ + + /** + * 客户端序列化请求对象 + * @param request 待发送给服务端的对象 + * @throws Exception 序列化异常 + */ + ByteBuf encodeRequest(Request request) throws Exception; + + /** + * do something if needed before client send request + */ + void beforeRequestSent(Request request, RpcClient rpcClient, BrpcChannel channelGroup); + + /** + * 客户端反序列化rpc响应 + * @param msg header & body的buf + * @param ctx netty channel context + * @throws Exception 反序列化异常 + */ + Response decodeResponse(Object msg, ChannelHandlerContext ctx) throws Exception; + + /** + * 连接被归还入池的时机 + * @return true代表请求发送后立即归还连接,false表示收到响应后归还。 + */ + boolean returnChannelBeforeResponse(); + + /**************** 仅服务端需要实现的函数 *******************/ + + /** + * 服务端反序列化rpc请求 + * @param packet header & body的buf + */ + Request decodeRequest(Object packet) throws Exception; + + /** + * 服务端序列化返回结果。 + * @param response 服务端要返回给客户端的对象 + * @throws Exception 序列化异常 + */ + ByteBuf encodeResponse(Request request, Response response) throws Exception; + + /** + * do something if needed after server channel writeAndFlush + * @param channelFuture the return value of writeAndFlush + */ + void afterResponseSent(Request request, Response response, ChannelFuture channelFuture); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolFactory.java new file mode 100644 index 00000000..0fdaa680 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolFactory.java @@ -0,0 +1,13 @@ +package com.baidu.brpc.protocol; + +public interface ProtocolFactory { + /** + * protocol priority controls the order of server parsing request. + * the lower priority will be parsed earlier. + */ + Integer DEFAULT_PRIORITY = 100; + + Integer getProtocolType(); + Integer getPriority(); + Protocol createProtocol(String encoding); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolManager.java new file mode 100644 index 00000000..befb59cb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/ProtocolManager.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Slf4j +public class ProtocolManager { + private Map protocolFactoryMap = new HashMap(); + private Map protocolMap = new HashMap(); + private List coexistenceProtocols = new ArrayList(); + private int coexistenceProtocolSize = 0; + + private static ProtocolManager instance; + + public static ProtocolManager getInstance() { + if (instance == null) { + synchronized (ProtocolManager.class) { + if (instance == null) { + instance = new ProtocolManager(); + } + } + } + return instance; + } + + private ProtocolManager() { + } + + /** + * application can register custom protocol + */ + public void registerProtocol(ProtocolFactory protocolFactory, String encoding) { + Integer protocolType = protocolFactory.getProtocolType(); + if (protocolFactoryMap.get(protocolType) != null) { + throw new RuntimeException("protocol exist, type=" + protocolType); + } + Protocol protocol = protocolFactory.createProtocol(encoding); + protocolMap.put(protocolType, protocol); + protocolFactoryMap.put(protocolType, protocolFactory); + if (protocol.isCoexistence()) { + coexistenceProtocols.add(protocol); + coexistenceProtocolSize++; + } + log.info("register protocol:{} success", protocolType); + } + + public Protocol getProtocol(Integer protocolType) { + Protocol protocol = protocolMap.get(protocolType); + if (protocol != null) { + return protocol; + } + + throw new RuntimeException("protocol not exist, type=" + protocolType); + } + + public Map getProtocolMap() { + return protocolMap; + } + + public List getCoexistenceProtocols() { + return coexistenceProtocols; + } + + public int getCoexistenceProtocolSize() { + return coexistenceProtocolSize; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Request.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Request.java new file mode 100644 index 00000000..12a17961 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Request.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.push.SPHead; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.FullHttpRequest; + +public interface Request { + + /** + * The msg param is the real request content to sent by netty. + * For http protocols, the msg is an instance of {@link FullHttpRequest}. + * For tcp protocols, the msg may be an instance of byte[]. + * + * @see HttpRequest + * @see RpcRequest + */ + Object getMsg(); + + void setMsg(Object o); + + /** + * used to find RpcFuture, application can not set it. + * @return rpc future id + */ + long getCorrelationId(); + + void setCorrelationId(long correlationId); + + /** + * used to identify request for application, application can set it. + * @return application request id + */ + long getLogId(); + + void setLogId(long logId); + + Object getTarget(); + + void setTarget(Object obj); + + Method getTargetMethod(); + + void setTargetMethod(Method method); + + RpcMethodInfo getRpcMethodInfo(); + + void setRpcMethodInfo(RpcMethodInfo rpcMethodInfo); + + String getServiceName(); + + void setServiceName(String serviceName); + + String getMethodName(); + + void setMethodName(String methodName); + + Object[] getArgs(); + + void setArgs(Object[] newArgs); + + Map getKvAttachment(); + + void setKvAttachment(Map requestKvAttachment); + + ByteBuf getBinaryAttachment(); + + void setBinaryAttachment(ByteBuf requestBinaryAttachment); + + int getCompressType(); + + void setCompressType(int number); + + RpcException getException(); + + void setException(RpcException e); + + Channel getChannel(); + + void setChannel(Channel channel); + + Set getSelectedInstances(); + + void setSelectedInstances(Set selectedInstances); + + NSHead getNsHead(); + + void setNsHead(NSHead nsHead); + + SPHead getSpHead(); + + void setSpHead(SPHead spHead); + + Request retain(); + + void release(); + + void reset(); + + String getAuth(); + + void setAuth(String auth); + + Long getTraceId(); + + void setTraceId(Long traceId); + + Long getSpanId(); + + void setSpanId(Long spanId); + + Long getParentSpanId(); + + void setParentSpanId(Long parentSpanId); + + RpcCallback getCallback(); + + void setCallback(RpcCallback callback); + + String getServiceTag(); + + void setServiceTag(String serviceTag); + + SubscribeInfo getSubscribeInfo(); + + void setSubscribeInfo(SubscribeInfo subscribeInfo); + + Integer getReadTimeoutMillis(); + + void setReadTimeoutMillis(Integer readTimeoutMillis); + + Integer getWriteTimeoutMillis(); + + void setWriteTimeoutMillis(Integer writeTimeoutMillis); + + void setClientName(String clientName); + + String getClientName(); + + boolean isOneWay(); + + void setOneWay(boolean oneWay); + + RpcFuture getRpcFuture(); + + void setRpcFuture(RpcFuture rpcFuture); + + ByteBuf getSendBuf(); + + void setSendBuf(ByteBuf sendBuf); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Response.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Response.java new file mode 100644 index 00000000..ebdfa563 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/Response.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. + */ + +package com.baidu.brpc.protocol; + +import java.util.Map; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.push.SPHead; + +import io.netty.buffer.ByteBuf; + +public interface Response { + Object getResult(); + + void setResult(Object result); + + /** + * used to find RpcFuture, application can not set it. + * @return rpc future id + */ + long getCorrelationId(); + + void setCorrelationId(long correlationId); + + /** + * used to identify request for application, application can set it. + * @return application request id + */ + long getLogId(); + + void setLogId(long logId); + + Throwable getException(); + + NSHead getNsHead(); + + SPHead getSpHead(); + + void setNsHead(NSHead nsHead); + + void setException(Throwable exception); + + RpcMethodInfo getRpcMethodInfo(); + + void setRpcMethodInfo(RpcMethodInfo rpcMethodInfo); + + RpcFuture getRpcFuture(); + + void setRpcFuture(RpcFuture rpcFuture); + + Map getKvAttachment(); + + void setKvAttachment(Map kvAttachment); + + ByteBuf getBinaryAttachment(); + + void setBinaryAttachment(ByteBuf binaryAttachment); + + int getCompressType(); + + void setCompressType(int compressType); + + void reset(); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcRequest.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcRequest.java new file mode 100644 index 00000000..31dbeaeb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcRequest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import io.netty.util.concurrent.FastThreadLocal; +import lombok.Getter; +import lombok.Setter; + +/** + * Bprc tcp request implementation, used for tcp protocols. + * + * @author wangjiayin@baidu.com + * @since 2018-12-26 + */ +@Setter +@Getter +public class RpcRequest extends AbstractRequest { + + private static final FastThreadLocal CURRENT_RPC_REQUEST = new FastThreadLocal() { + @Override + protected RpcRequest initialValue() { + return new RpcRequest(); + } + }; + + public static RpcRequest getRpcRequest() { + return CURRENT_RPC_REQUEST.get(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcResponse.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcResponse.java new file mode 100644 index 00000000..8c7a1d3b --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/RpcResponse.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol; + +import io.netty.util.concurrent.FastThreadLocal; +import lombok.Getter; +import lombok.Setter; + +/** + * Bprc tcp response implementation, used for tcp protocols. + * + * @author wangjiayin@baidu.com + * @since 2018-12-26 + */ +@Setter +@Getter +public class RpcResponse extends AbstractResponse { + + private static final FastThreadLocal CURRENT_RPC_RESPONSE = new FastThreadLocal() { + @Override + protected RpcResponse initialValue() { + return new RpcResponse(); + } + }; + + public static RpcResponse getRpcResponse() { + return CURRENT_RPC_RESPONSE.get(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectAggregator.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectAggregator.java new file mode 100644 index 00000000..c844c3ba --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectAggregator.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import java.util.List; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpObject; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.util.ReferenceCountUtil; + +/** + * Migrate from netty {@link HttpObjectAggregator} + * + * @author wangjiayin@baidu.com + * @since 2019-01-07 + */ +public class BrpcHttpObjectAggregator extends HttpObjectAggregator { + + public BrpcHttpObjectAggregator(int maxContentLength) { + super(maxContentLength); + } + + public void aggregate(final ChannelHandlerContext ctx, Object msg, List out) throws Exception { + if (acceptInboundMessage(msg)) { + try { + decode(ctx, (HttpObject) msg, out); + } finally { + ReferenceCountUtil.release(msg); + } + } else { + out.add(msg); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectDecoder.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectDecoder.java new file mode 100644 index 00000000..bc6da8e0 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectDecoder.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import java.util.LinkedList; +import java.util.List; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.DefaultHttpRequest; +import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpObjectDecoder; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.concurrent.FastThreadLocal; +import io.netty.util.internal.StringUtil; + +/** + * Migrate from netty {@link HttpObjectDecoder} + * + * @author wangjiayin@baidu.com + * @since 2019-01-07 + */ +public class BrpcHttpObjectDecoder extends HttpObjectDecoder { + + private static final FastThreadLocal CURRENT_RPC_RESPONSE = + new FastThreadLocal() { + @Override + protected BrpcHttpObjectDecoder initialValue() { + return new BrpcHttpObjectDecoder(true); + } + }; + + public static BrpcHttpObjectDecoder getDecoder(boolean isDecodingRequest) { + BrpcHttpObjectDecoder decoder = CURRENT_RPC_RESPONSE.get(); + decoder.isDecodingRequest = isDecodingRequest; + return decoder; + } + + private static final HttpResponseStatus UNKNOWN_STATUS = new HttpResponseStatus(999, "Unknown"); + + // private BrpcHttpObjectAggregator httpObjectAggregator = new BrpcHttpObjectAggregator(10 * 1024 * 1024); + + private boolean isDecodingRequest; + + private BrpcHttpObjectDecoder(boolean isDecodingRequest) { + super(); + this.isDecodingRequest = isDecodingRequest; + } + + @Override + protected HttpMessage createMessage(String[] initialLine) throws Exception { + + return isDecodingRequest() ? new DefaultHttpRequest( + HttpVersion.valueOf(initialLine[2]), + HttpMethod.valueOf(initialLine[0]), initialLine[1], validateHeaders) : + new DefaultHttpResponse( + HttpVersion.valueOf(initialLine[0]), + HttpResponseStatus.valueOf(Integer.parseInt(initialLine[1]), initialLine[2]), validateHeaders); + } + + @Override + protected HttpMessage createInvalidMessage() { + return isDecodingRequest() ? + new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/bad-request", validateHeaders) : + new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, UNKNOWN_STATUS, validateHeaders); + } + + @Override + protected boolean isDecodingRequest() { + return isDecodingRequest; + } + + /** + * a ByteToMessageDecoder for http message + * + * @return DefaultHttpRequest or DefaultHttpResponse instance if success. + * If there's not enough bytes, method will return null + */ + public Object decode(ChannelHandlerContext ctx, ByteBuf in) { + BrpcHttpObjectAggregator httpObjectAggregator = new BrpcHttpObjectAggregator(10 * 1024 * 1024); + this.reset(); + List httpParts = new LinkedList(); + List httpResult = new LinkedList(); + try { + while (in.isReadable()) { + int outSize = httpParts.size(); + + if (outSize > 0) { + for (int i = 0; i < outSize; i++) { + httpObjectAggregator.aggregate(ctx, httpParts.get(i), httpResult); + if (httpResult.size() > 0) { + return httpResult.get(0); + } + } + // fireChannelRead(ctx, out, outSize); + httpParts.clear(); + + // Check if this handler was removed before continuing with decoding. + // If it was removed, it is not safe to continue to operate on the buffer. + // + // See: + // - https://github.com/netty/netty/issues/4635 + if (ctx.isRemoved()) { + break; + } + outSize = 0; + } + + int oldInputLength = in.readableBytes(); + decode(ctx, in, httpParts); + // decodeRemovalReentryProtection(ctx, in, out); + + // Check if this handler was removed before continuing the loop. + // If it was removed, it is not safe to continue to operate on the buffer. + // + // See https://github.com/netty/netty/issues/1664 + if (ctx.isRemoved()) { + break; + } + + if (outSize == httpParts.size()) { + if (oldInputLength == in.readableBytes()) { + break; + } else { + continue; + } + } + + if (oldInputLength == in.readableBytes()) { + throw new DecoderException( + StringUtil.simpleClassName(getClass()) + + ".decode() did not read anything but decoded a message."); + } + + if (isSingleDecode()) { + break; + } + } + int outSize = httpParts.size(); + if (outSize > 0) { + for (int i = 0; i < outSize; i++) { + httpObjectAggregator.aggregate(ctx, httpParts.get(i), httpResult); + if (httpResult.size() > 0) { + return httpResult.get(0); + } + } + } + // decode failed, there's not enough bytes + return null; + } catch (DecoderException e) { + throw e; + } catch (Exception cause) { + throw new DecoderException(cause); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectEncoder.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectEncoder.java new file mode 100644 index 00000000..83f797df --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpObjectEncoder.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import static io.netty.buffer.Unpooled.directBuffer; +import static io.netty.buffer.Unpooled.unreleasableBuffer; +import static io.netty.handler.codec.http.HttpConstants.CR; +import static io.netty.handler.codec.http.HttpConstants.LF; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.CompositeByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.buffer.UnpooledByteBufAllocator; +import io.netty.channel.FileRegion; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpObject; +import io.netty.handler.codec.http.HttpObjectEncoder; +import io.netty.handler.codec.http.HttpUtil; +import io.netty.handler.codec.http.LastHttpContent; +import io.netty.util.CharsetUtil; +import io.netty.util.internal.StringUtil; + +/** + * Migrate from netty {@link HttpObjectEncoder} + * + * @author wangjiayin@baidu.com + * @since 2019-01-12 + */ +public abstract class BrpcHttpObjectEncoder { + static final int CRLF_SHORT = (CR << 8) | LF; + private static final int ZERO_CRLF_MEDIUM = ('0' << 16) | CRLF_SHORT; + private static final byte[] ZERO_CRLF_CRLF = {'0', CR, LF, CR, LF}; + private static final ByteBuf CRLF_BUF = unreleasableBuffer(directBuffer(2).writeByte(CR).writeByte(LF)); + private static final ByteBuf ZERO_CRLF_CRLF_BUF = unreleasableBuffer(directBuffer(ZERO_CRLF_CRLF.length) + .writeBytes(ZERO_CRLF_CRLF)); + private static final float HEADERS_WEIGHT_NEW = 1 / 5f; + private static final float HEADERS_WEIGHT_HISTORICAL = 1 - HEADERS_WEIGHT_NEW; + private static final float TRAILERS_WEIGHT_NEW = HEADERS_WEIGHT_NEW; + private static final float TRAILERS_WEIGHT_HISTORICAL = HEADERS_WEIGHT_HISTORICAL; + + private static final int ST_INIT = 0; + private static final int ST_CONTENT_NON_CHUNK = 1; + private static final int ST_CONTENT_CHUNK = 2; + private static final int ST_CONTENT_ALWAYS_EMPTY = 3; + + @SuppressWarnings("RedundantFieldInitialization") + private int state = ST_INIT; + + /** + * Used to calculate an exponential moving average of the encoded size of the initial line and the headers for + * a guess for future buffer allocations. + */ + private float headersEncodedSizeAccumulator = 256; + + /** + * Used to calculate an exponential moving average of the encoded size of the trailers for + * a guess for future buffer allocations. + */ + private float trailersEncodedSizeAccumulator = 256; + + protected void encode(Object msg, List out) throws Exception { + ByteBuf buf = null; + if (msg instanceof HttpMessage) { + if (state != ST_INIT) { + throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg) + + ", state: " + state); + } + + @SuppressWarnings({"unchecked", "CastConflictsWithInstanceof"}) + H m = (H) msg; + + buf = new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, (int) headersEncodedSizeAccumulator); + // buf = ctx.alloc().buffer((int) headersEncodedSizeAccumulator); + // Encode the message. + encodeInitialLine(buf, m); + state = isContentAlwaysEmpty(m) ? ST_CONTENT_ALWAYS_EMPTY : + HttpUtil.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK; + + sanitizeHeadersBeforeEncode(m, state == ST_CONTENT_ALWAYS_EMPTY); + + encodeHeaders(m.headers(), buf); + ByteBufUtil.writeShortBE(buf, CRLF_SHORT); + + headersEncodedSizeAccumulator = HEADERS_WEIGHT_NEW * padSizeForAccumulation(buf.readableBytes()) + + HEADERS_WEIGHT_HISTORICAL * headersEncodedSizeAccumulator; + } + + // Bypass the encoder in case of an empty buffer, so that the following idiom works: + // + // ch.write(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); + // + // See https://github.com/netty/netty/issues/2983 for more information. + // if (msg instanceof ByteBuf) { + // final ByteBuf potentialEmptyBuf = (ByteBuf) msg; + // if (!potentialEmptyBuf.isReadable()) { + // out.add(potentialEmptyBuf.retain()); + // return; + // } + // } + + if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) { + switch (state) { + case ST_INIT: + throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); + case ST_CONTENT_NON_CHUNK: + final long contentLength = contentLength(msg); + if (contentLength > 0 && msg instanceof HttpContent) { + if (buf != null) { + buf.ensureWritable((int) contentLength); + buf.writeBytes(((HttpContent) msg).content()); + out.add(buf); + } + + // if (buf != null && buf.writableBytes() >= contentLength && msg instanceof HttpContent) { + // // merge into other buffer for performance reasons + // buf.writeBytes(((HttpContent) msg).content()); + // out.add(buf); + // } else { + // if (buf != null) { + // out.add(buf); + // } + // out.add(encodeAndRetain(msg)); + // } + // + // if (msg instanceof LastHttpContent) { + // state = ST_INIT; + // } + + break; + } + + // fall-through! + case ST_CONTENT_ALWAYS_EMPTY: + + if (buf != null) { + // We allocated a buffer so add it now. + out.add(buf); + } else { + // Need to produce some output otherwise an + // IllegalStateException will be thrown as we did not write anything + // Its ok to just write an EMPTY_BUFFER as if there are reference count issues these will be + // propagated as the caller of the encode(...) method will release the original + // buffer. + // Writing an empty buffer will not actually write anything on the wire, so if there is a user + // error with msg it will not be visible externally + out.add(Unpooled.EMPTY_BUFFER); + } + + break; + case ST_CONTENT_CHUNK: + if (buf != null) { + // We allocated a buffer so add it now. + out.add(buf); + } + encodeChunkedContent(msg, contentLength(msg), out); + + break; + default: + throw new Error(); + } + + if (msg instanceof LastHttpContent) { + state = ST_INIT; + } + } else if (buf != null) { + out.add(buf); + } + } + + /** + * Encode the {@link HttpHeaders} into a {@link ByteBuf}. + */ + protected void encodeHeaders(HttpHeaders headers, ByteBuf buf) { + Iterator> iter = headers.iteratorCharSequence(); + while (iter.hasNext()) { + Map.Entry header = iter.next(); + HttpHeadersEncoder.encoderHeader(header.getKey(), header.getValue(), buf); + } + } + + private void encodeChunkedContent(Object msg, long contentLength, List out) { + if (contentLength > 0) { + String lengthHex = Long.toHexString(contentLength); + ByteBuf buf = new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, lengthHex.length() + 2); + buf.writeCharSequence(lengthHex, CharsetUtil.US_ASCII); + ByteBufUtil.writeShortBE(buf, CRLF_SHORT); + out.add(buf); + out.add(encodeAndRetain(msg)); + out.add(CRLF_BUF.duplicate()); + } + + if (msg instanceof LastHttpContent) { + HttpHeaders headers = ((LastHttpContent) msg).trailingHeaders(); + if (headers.isEmpty()) { + out.add(ZERO_CRLF_CRLF_BUF.duplicate()); + } else { + ByteBuf buf = new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, + (int) trailersEncodedSizeAccumulator); + ByteBufUtil.writeMediumBE(buf, ZERO_CRLF_MEDIUM); + encodeHeaders(headers, buf); + ByteBufUtil.writeShortBE(buf, CRLF_SHORT); + trailersEncodedSizeAccumulator = TRAILERS_WEIGHT_NEW * padSizeForAccumulation(buf.readableBytes()) + + TRAILERS_WEIGHT_HISTORICAL * trailersEncodedSizeAccumulator; + out.add(buf); + } + } else if (contentLength == 0) { + // Need to produce some output otherwise an + // IllegalStateException will be thrown + out.add(encodeAndRetain(msg)); + } + } + + /** + * Allows to sanitize headers of the message before encoding these. + */ + protected void sanitizeHeadersBeforeEncode(@SuppressWarnings("unused") H msg, boolean isAlwaysEmpty) { + // noop + } + + /** + * Determine whether a message has a content or not. Some message may have headers indicating + * a content without having an actual content, e.g the response to an HEAD or CONNECT request. + * + * @param msg the message to test + * + * @return {@code true} to signal the message has no content + */ + protected boolean isContentAlwaysEmpty(@SuppressWarnings("unused") H msg) { + return false; + } + + public boolean acceptOutboundMessage(Object msg) throws Exception { + return msg instanceof HttpObject || msg instanceof ByteBuf || msg instanceof FileRegion; + } + + private static Object encodeAndRetain(Object msg) { + if (msg instanceof ByteBuf) { + return ((ByteBuf) msg).retain(); + } + if (msg instanceof HttpContent) { + return ((HttpContent) msg).content().retain(); + } + if (msg instanceof FileRegion) { + return ((FileRegion) msg).retain(); + } + throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); + } + + private static long contentLength(Object msg) { + if (msg instanceof HttpContent) { + return ((HttpContent) msg).content().readableBytes(); + } + if (msg instanceof ByteBuf) { + return ((ByteBuf) msg).readableBytes(); + } + if (msg instanceof FileRegion) { + return ((FileRegion) msg).count(); + } + throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); + } + + /** + * Add some additional overhead to the buffer. The rational is that it is better to slightly over allocate and waste + * some memory, rather than under allocate and require a resize/copy. + * + * @param readableBytes The readable bytes in the buffer. + * + * @return The {@code readableBytes} with some additional padding. + */ + private static int padSizeForAccumulation(int readableBytes) { + return (readableBytes << 2) / 3; + } + + @Deprecated + protected static void encodeAscii(String s, ByteBuf buf) { + buf.writeCharSequence(s, CharsetUtil.US_ASCII); + } + + protected abstract void encodeInitialLine(ByteBuf buf, H message) throws Exception; + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpRequestEncoder.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpRequestEncoder.java new file mode 100644 index 00000000..a5b14b05 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpRequestEncoder.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import static io.netty.handler.codec.http.HttpConstants.SP; + +import java.util.LinkedList; +import java.util.List; + +import com.baidu.brpc.exceptions.RpcException; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpRequestEncoder; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.util.CharsetUtil; + +/** + * Migrate from netty {@link HttpRequestEncoder} + * + * @author wangjiayin@baidu.com + * @since 2019-01-12 + */ +public class BrpcHttpRequestEncoder extends BrpcHttpObjectEncoder { + + private static final char SLASH = '/'; + private static final char QUESTION_MARK = '?'; + private static final int SLASH_AND_SPACE_SHORT = (SLASH << 8) | SP; + private static final int SPACE_SLASH_AND_SPACE_MEDIUM = (SP << 16) | SLASH_AND_SPACE_SHORT; + + @Override + public boolean acceptOutboundMessage(Object msg) throws Exception { + return super.acceptOutboundMessage(msg) && !(msg instanceof HttpResponse); + } + + @Override + protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception { + ByteBufUtil.copy(request.method().asciiName(), buf); + + String uri = request.uri(); + + if (uri.isEmpty()) { + // Add " / " as absolute path if uri is not present. + // See http://tools.ietf.org/html/rfc2616#section-5.1.2 + ByteBufUtil.writeMediumBE(buf, SPACE_SLASH_AND_SPACE_MEDIUM); + } else { + CharSequence uriCharSequence = uri; + boolean needSlash = false; + int start = uri.indexOf("://"); + if (start != -1 && uri.charAt(0) != SLASH) { + start += 3; + // Correctly handle query params. + // See https://github.com/netty/netty/issues/2732 + int index = uri.indexOf(QUESTION_MARK, start); + if (index == -1) { + if (uri.lastIndexOf(SLASH) < start) { + needSlash = true; + } + } else { + if (uri.lastIndexOf(SLASH, index) < start) { + uriCharSequence = new StringBuilder(uri).insert(index, SLASH); + } + } + } + buf.writeByte(SP).writeCharSequence(uriCharSequence, CharsetUtil.UTF_8); + if (needSlash) { + // write "/ " after uri + ByteBufUtil.writeShortBE(buf, SLASH_AND_SPACE_SHORT); + } else { + buf.writeByte(SP); + } + } + + buf.writeCharSequence(request.protocolVersion().text(), CharsetUtil.US_ASCII); + ByteBufUtil.writeShortBE(buf, CRLF_SHORT); + } + + public ByteBuf encode(Object msg) throws Exception { + List list = new LinkedList(); + super.encode(msg, list); + if (list.size() == 1) { + return (ByteBuf) list.get(0); + } else { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "encode request failed"); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpResponseEncoder.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpResponseEncoder.java new file mode 100644 index 00000000..93c11458 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/BrpcHttpResponseEncoder.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import static io.netty.handler.codec.http.HttpConstants.SP; + +import java.util.LinkedList; +import java.util.List; + +import com.baidu.brpc.exceptions.RpcException; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpStatusClass; +import io.netty.util.CharsetUtil; + +/** + * Migrate from netty {@link HttpResponseEncoder} + * + * @author wangjiayin@baidu.com + * @since 2019-01-07 + */ +public class BrpcHttpResponseEncoder extends BrpcHttpObjectEncoder { + + @Override + public boolean acceptOutboundMessage(Object msg) throws Exception { + return super.acceptOutboundMessage(msg) && !(msg instanceof HttpRequest); + } + + @Override + protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception { + buf.writeCharSequence(response.protocolVersion().text(), CharsetUtil.US_ASCII); + buf.writeByte(SP); + ByteBufUtil.copy(response.status().codeAsText(), buf); + buf.writeByte(SP); + buf.writeCharSequence(response.status().reasonPhrase(), CharsetUtil.US_ASCII); + ByteBufUtil.writeShortBE(buf, CRLF_SHORT); + } + + @Override + protected void sanitizeHeadersBeforeEncode(HttpResponse msg, boolean isAlwaysEmpty) { + if (isAlwaysEmpty) { + HttpResponseStatus status = msg.status(); + if (status.codeClass() == HttpStatusClass.INFORMATIONAL + || status.code() == HttpResponseStatus.NO_CONTENT.code()) { + + // Stripping Content-Length: + // See https://tools.ietf.org/html/rfc7230#section-3.3.2 + msg.headers().remove(HttpHeaderNames.CONTENT_LENGTH); + + // Stripping Transfer-Encoding: + // See https://tools.ietf.org/html/rfc7230#section-3.3.1 + msg.headers().remove(HttpHeaderNames.TRANSFER_ENCODING); + } else if (status.code() == HttpResponseStatus.RESET_CONTENT.code()) { + + // Stripping Transfer-Encoding: + msg.headers().remove(HttpHeaderNames.TRANSFER_ENCODING); + + // Set Content-Length: 0 + // https://httpstatuses.com/205 + msg.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, 0); + } + } + } + + @Override + protected boolean isContentAlwaysEmpty(HttpResponse msg) { + // Correctly handle special cases as stated in: + // https://tools.ietf.org/html/rfc7230#section-3.3.3 + HttpResponseStatus status = msg.status(); + + if (status.codeClass() == HttpStatusClass.INFORMATIONAL) { + + if (status.code() == HttpResponseStatus.SWITCHING_PROTOCOLS.code()) { + // We need special handling for WebSockets version 00 as it will include an body. + // Fortunally this version should not really be used in the wild very often. + // See https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-1.2 + return msg.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_VERSION); + } + return true; + } + return status.code() == HttpResponseStatus.NO_CONTENT.code() + || status.code() == HttpResponseStatus.NOT_MODIFIED.code() + || status.code() == HttpResponseStatus.RESET_CONTENT.code(); + } + + public ByteBuf encode(Object msg) throws Exception { + List list = new LinkedList(); + super.encode(msg, list); + if (list.size() == 1) { + return (ByteBuf) list.get(0); + } else { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "encode response failed"); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpHeadersEncoder.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpHeadersEncoder.java new file mode 100644 index 00000000..9fe0beea --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpHeadersEncoder.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.http; + +import static com.baidu.brpc.protocol.http.BrpcHttpObjectEncoder.CRLF_SHORT; +import static io.netty.handler.codec.http.HttpConstants.COLON; +import static io.netty.handler.codec.http.HttpConstants.SP; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.util.AsciiString; +import io.netty.util.CharsetUtil; + +public class HttpHeadersEncoder { + + private static final int COLON_AND_SPACE_SHORT = (COLON << 8) | SP; + + private HttpHeadersEncoder() { + } + + static void encoderHeader(CharSequence name, CharSequence value, ByteBuf buf) { + final int nameLen = name.length(); + final int valueLen = value.length(); + final int entryLen = nameLen + valueLen + 4; + buf.ensureWritable(entryLen); + int offset = buf.writerIndex(); + writeAscii(buf, offset, name); + offset += nameLen; + ByteBufUtil.setShortBE(buf, offset, COLON_AND_SPACE_SHORT); + offset += 2; + writeAscii(buf, offset, value); + offset += valueLen; + ByteBufUtil.setShortBE(buf, offset, CRLF_SHORT); + offset += 2; + buf.writerIndex(offset); + } + + private static void writeAscii(ByteBuf buf, int offset, CharSequence value) { + if (value instanceof AsciiString) { + ByteBufUtil.copy((AsciiString) value, 0, buf, offset, value.length()); + } else { + buf.setCharSequence(offset, value, CharsetUtil.US_ASCII); + } + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpJsonProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpJsonProtocolFactory.java new file mode 100644 index 00000000..f99255fc --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpJsonProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.http; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class HttpJsonProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY + 1; + } + + @Override + public Protocol createProtocol(String encoding) { + return new HttpRpcProtocol(getProtocolType(), encoding); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpProtobufProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpProtobufProtocolFactory.java new file mode 100644 index 00000000..9258608c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpProtobufProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.http; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class HttpProtobufProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY - 1; + } + + @Override + public Protocol createProtocol(String encoding) { + return new HttpRpcProtocol(getProtocolType(), encoding); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcProtocol.java new file mode 100644 index 00000000..a0ae3207 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcProtocol.java @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import com.google.gson.*; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.naming.DnsNamingService; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.BrpcMeta; +import com.baidu.brpc.protocol.HttpRequest; +import com.baidu.brpc.protocol.HttpResponse; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.server.ServiceManager; + +import com.google.protobuf.Descriptors; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.Message; +import com.googlecode.protobuf.format.JsonFormat; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaderValues; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpUtil; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.QueryStringDecoder; + +/** + * 处理http rpc协议,包括四种序列化格式: + * 1、http + protobuf + * 2、http + json + */ +public class HttpRpcProtocol extends AbstractProtocol { + public static final String PROTOCOL_TYPE = "protocol-type"; + private static final Logger LOG = LoggerFactory.getLogger(HttpRpcProtocol.class); + private static final String CONTENT_TYPE_JSON = "application/json"; + private static final String CONTENT_TYPE_PROTOBUF = "application/proto"; + /** + * 请求的唯一标识id + */ + private static final String CORRELATION_ID = "correlation-id"; + private static final JsonFormat jsonPbConverter = new JsonFormat() { + protected void print(Message message, JsonGenerator generator) throws IOException { + for (Iterator> iter = + message.getAllFields().entrySet().iterator(); iter.hasNext(); ) { + Map.Entry field = iter.next(); + printField(field.getKey(), field.getValue(), generator); + if (iter.hasNext()) { + generator.print(","); + } + } + // ignore UnknownFields + } + }; + private static final Gson gson = (new GsonBuilder()) + .serializeNulls() + .disableHtmlEscaping() + .serializeSpecialFloatingPointValues() + .create(); + private static final JsonParser jsonParser = new JsonParser(); + + // HTTP Headers which should not be modified by user + private static final Set prohibitedHeaders = new HashSet(); + + static { + prohibitedHeaders.add(HttpHeaderNames.CONTENT_TYPE.toString()); + prohibitedHeaders.add(HttpHeaderNames.CONTENT_LENGTH.toString()); + prohibitedHeaders.add(HttpHeaderNames.CONNECTION.toString()); + prohibitedHeaders.add(CORRELATION_ID); + } + + + protected int protocolType; + protected String encoding; + + public HttpRpcProtocol(int protocolType, String encoding) { + this.protocolType = protocolType; + this.encoding = encoding; + } + + @Override + public Request createRequest() { + return new HttpRequest(); + } + + @Override + public Response createResponse() { + return new HttpResponse(); + } + + @Override + public Request getRequest() { + Request request = HttpRequest.getHttpRequest(); + request.reset(); + return request; + } + + @Override + public Response getResponse() { + Response response = HttpResponse.getHttpResponse(); + response.reset(); + return response; + } + + @Override + public Object decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + HttpMessage httpMessage = null; + // I don't know the length of http header, so here copy all readable bytes to decode + ByteBuf byteBuf = in.retainedSlice(in.readableBytes()); + boolean decodeSuccess = false; + try { + // TODO: only parse header + httpMessage = (HttpMessage) BrpcHttpObjectDecoder.getDecoder(isDecodingRequest).decode(ctx, byteBuf); + if (httpMessage != null) { + if (httpMessage.decoderResult() != null && httpMessage.decoderResult().isFailure()) { + // could not decode http message + LOG.debug("failed to decode http message", httpMessage.decoderResult().cause()); + throw new BadSchemaException(); + } + String contentTypeAndEncoding = httpMessage.headers().get(HttpHeaderNames.CONTENT_TYPE); + // if content-type does not exist, it is /status request, so this protocol can deal with. + if (StringUtils.isNoneBlank(contentTypeAndEncoding)) { + contentTypeAndEncoding = contentTypeAndEncoding.toLowerCase(); + String[] splits = StringUtils.split(contentTypeAndEncoding, ";"); + String contentType = splits[0]; + if (!contentType.equals(CONTENT_TYPE_PROTOBUF) + && !contentType.equals(CONTENT_TYPE_JSON)) { + // this protocol can only deal with http protobuf and http json request. + httpMessage = null; + throw new BadSchemaException(); + } + } + decodeSuccess = true; + } + } catch (Exception e) { + throw new BadSchemaException(); + } finally { + if (decodeSuccess) { + in.skipBytes(byteBuf.readerIndex()); + } + byteBuf.release(); + } + + if (httpMessage == null) { + // decode next time + throw notEnoughDataException; + } + + return httpMessage; + } + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + HttpRequest httpRequest = (HttpRequest) request; + String serviceName = httpRequest.getTargetMethod().getDeclaringClass().getName(); + String methodName = httpRequest.getTargetMethod().getName(); + BrpcMeta rpcMeta = httpRequest.getTargetMethod().getAnnotation(BrpcMeta.class); + if (rpcMeta != null) { + serviceName = rpcMeta.serviceName(); + methodName = rpcMeta.methodName(); + } + LOG.debug("serviceName={}, methodName={}", serviceName, methodName); + + Object httpRequestBody = makeRequest((int) httpRequest.getLogId(), methodName, httpRequest.getArgs()); + byte[] httpRequestBodyBytes = + encodeBody(protocolType, encoding, httpRequestBody, httpRequest.getRpcMethodInfo()); + + FullHttpRequest nettyHttpRequest = null; + try { + nettyHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, ""); + nettyHttpRequest.setUri(buildHttpUri(serviceName, methodName)); + if (httpRequestBodyBytes != null) { + nettyHttpRequest.content().writeBytes(httpRequestBodyBytes); + } + String contentType = getContentType(protocolType); + nettyHttpRequest.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=" + encoding); + nettyHttpRequest.headers().set(HttpHeaderNames.CONTENT_LENGTH, httpRequestBodyBytes == null + ? 0 : httpRequestBodyBytes.length); + nettyHttpRequest.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + nettyHttpRequest.headers().set(CORRELATION_ID, httpRequest.getCorrelationId()); + for (Map.Entry header : httpRequest.headers()) { + if (prohibitedHeaders.contains(header.getKey().toLowerCase())) { + continue; + } + nettyHttpRequest.headers().set(header.getKey(), header.getValue()); + } + if (request.getKvAttachment() != null) { + for (Map.Entry kv : request.getKvAttachment().entrySet()) { + if (!prohibitedHeaders.contains(kv.getKey().toLowerCase())) { + nettyHttpRequest.headers().set(kv.getKey(), kv.getValue()); + } + } + } + BrpcHttpRequestEncoder encoder = new BrpcHttpRequestEncoder(); + return encoder.encode(nettyHttpRequest); + } finally { + if (nettyHttpRequest != null) { + nettyHttpRequest.release(); + } + } + } + + @Override + public void beforeRequestSent(Request request, RpcClient rpcClient, BrpcChannel channelGroup) { + String hostPort; + HttpRequest httpRequest = (HttpRequest) request; + NamingService namingService = rpcClient.getNamingService(); + if (!httpRequest.headers().contains(HttpHeaderNames.HOST)) { + if (namingService != null && namingService instanceof DnsNamingService) { + // 从 DnsNamingService 获取原始的 host + hostPort = ((DnsNamingService) namingService).getHostPort(); + } else { + // 默认获取当前链接的 host:port 即可 + hostPort = channelGroup.getServiceInstance().getIp() + ":" + + channelGroup.getServiceInstance().getPort(); + } + // some http server decide what to do by the 'host' param in request header + httpRequest.headers().set(HttpHeaderNames.HOST, hostPort); + } + } + + @Override + public Response decodeResponse(Object msg, ChannelHandlerContext ctx) { + FullHttpResponse httpResponse = (FullHttpResponse) msg; + try { + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + Long correlationId = parseCorrelationId(httpResponse.headers().get(CORRELATION_ID), channelInfo.getCorrelationId()); + HttpResponse response = new HttpResponse(); + response.setCorrelationId(correlationId); + RpcFuture future = channelInfo.removeRpcFuture(response.getCorrelationId()); + if (future == null) { + return response; + } + response.setRpcFuture(future); + + int bodyLen = httpResponse.content().readableBytes(); + byte[] bytes = new byte[bodyLen]; + httpResponse.content().readBytes(bytes); + + if (!httpResponse.status().equals(HttpResponseStatus.OK)) { + String body = new String(bytes); + String message = String.format("http status=%d, message=%s", + httpResponse.status().code(), body); + LOG.warn("{}", message); + response.setException(new RpcException(RpcException.SERVICE_EXCEPTION, message)); + return response; + } + + String contentTypeAndEncoding = httpResponse.headers().get(HttpHeaderNames.CONTENT_TYPE).toLowerCase(); + String[] splits = StringUtils.split(contentTypeAndEncoding, ";"); + int protocolType = HttpRpcProtocol.parseProtocolType(splits[0]); + String encoding = this.encoding; + // 由于uc服务返回的encoding是错误的,所以这里以client端设置的encoding为准。 + // for (String split : splits) { + // split = split.trim(); + // if (split.startsWith("charset=")) { + // encoding = split.substring("charset=".length()); + // } + // } + + Object body = null; + if (bodyLen != 0) { + try { + body = decodeBody(protocolType, encoding, bytes); + } catch (Exception ex) { + LOG.error("decode response body failed"); + response.setException(ex); + return response; + } + } + + if (body != null) { + try { + response.setResult(parseHttpResponse(body, future.getRpcMethodInfo())); + } catch (Exception ex) { + LOG.error("failed to parse result from HTTP body"); + response.setException(ex); + } + } else { + response.setResult(null); + } + + // set response attachment + if (response.getKvAttachment() == null) { + response.setKvAttachment(new HashMap()); + } + for (Map.Entry entry : httpResponse.headers()) { + response.getKvAttachment().put(entry.getKey(), entry.getValue()); + } + + return response; + } finally { + httpResponse.release(); + } + } + + @Override + public Request decodeRequest(Object packet) { + try { + HttpRequest httpRequest = (HttpRequest) this.createRequest(); + httpRequest.setMsg(packet); + long correlationId = parseCorrelationId(httpRequest.headers().get(CORRELATION_ID), null); + httpRequest.setCorrelationId(correlationId); + + String contentTypeAndEncoding = httpRequest.headers().get(HttpHeaderNames.CONTENT_TYPE).toLowerCase(); + String[] splits = StringUtils.split(contentTypeAndEncoding, ";"); + int protocolType = HttpRpcProtocol.parseProtocolType(splits[0]); + String encoding = this.encoding; + for (String split : splits) { + split = split.trim(); + if (split.startsWith("charset=")) { + encoding = split.substring("charset=".length()); + } + } + httpRequest.headers().set(PROTOCOL_TYPE, protocolType); + httpRequest.headers().set(HttpHeaderNames.CONTENT_ENCODING, encoding); + + // set http headers to attachment + if (httpRequest.getKvAttachment() == null) { + httpRequest.setKvAttachment(new HashMap()); + } + for (Map.Entry entry : httpRequest.headers()) { + httpRequest.getKvAttachment().put(entry.getKey(), entry.getValue()); + } + + ByteBuf byteBuf = httpRequest.content(); + int bodyLen = byteBuf.readableBytes(); + if (bodyLen == 0) { + String errMsg = String.format("body should not be null, uri:%s", httpRequest.uri()); + LOG.warn(errMsg); + httpRequest.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errMsg)); + return httpRequest; + } + byte[] requestBytes = new byte[bodyLen]; + byteBuf.readBytes(requestBytes, 0, bodyLen); + Object body = decodeBody(protocolType, encoding, requestBytes); + + QueryStringDecoder queryStringDecoder = new QueryStringDecoder(httpRequest.uri()); + String path = queryStringDecoder.path(); + String serviceName = null; + String methodName = null; + if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE + || protocolType == Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE) { + String[] uriSplit = path.split("/"); + if (uriSplit.length < 3) { + String errMsg = String.format("url format is error, path:%s", path); + LOG.warn(errMsg); + httpRequest.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errMsg)); + return httpRequest; + } + serviceName = uriSplit[uriSplit.length - 2]; + methodName = uriSplit[uriSplit.length - 1]; + } else { + JsonObject bodyObject = (JsonObject) body; + methodName = bodyObject.get("method").getAsString(); + serviceName = path; + } + ServiceManager serviceManager = ServiceManager.getInstance(); + RpcMethodInfo rpcMethodInfo = serviceManager.getService(serviceName, methodName); + if (rpcMethodInfo == null) { + String errMsg = String.format("Fail to find path=%s", path); + LOG.warn(errMsg); + httpRequest.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errMsg)); + return httpRequest; + } + httpRequest.setServiceName(rpcMethodInfo.getServiceName()); + httpRequest.setMethodName(rpcMethodInfo.getMethodName()); + httpRequest.setRpcMethodInfo(rpcMethodInfo); + httpRequest.setTargetMethod(rpcMethodInfo.getMethod()); + httpRequest.setTarget(rpcMethodInfo.getTarget()); + httpRequest.setArgs(parseRequestParam(protocolType, body, rpcMethodInfo)); + return httpRequest; + } finally { + ((FullHttpRequest) packet).release(); + } + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) { + FullHttpRequest httpRequest = (FullHttpRequest) request.getMsg(); + FullHttpResponse httpResponse = null; + + try { + byte[] responseBytes; + if (response.getException() != null) { + httpResponse = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); + responseBytes = response.getException().toString().getBytes(); + } else { + httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + int protocolType = Integer.parseInt(httpRequest.headers().get(PROTOCOL_TYPE)); + Object body = makeResponse(protocolType, response); + // encode body + try { + responseBytes = encodeBody(protocolType, + httpRequest.headers().get(HttpHeaderNames.CONTENT_ENCODING), + body, response.getRpcMethodInfo()); + } catch (Exception e) { + LOG.warn("encode response failed", e); + response.setException(e); + httpResponse = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); + responseBytes = response.getException().toString().getBytes(); + } + } + httpResponse.content().writeBytes(responseBytes); + addHttpResponseHeaders(httpResponse, response, httpRequest); + // encode full http response + BrpcHttpResponseEncoder encoder = new BrpcHttpResponseEncoder(); + return encoder.encode(httpResponse); + } catch (Exception e) { + LOG.warn("encode response failed", e); + response.setException(e); + return null; + } finally { + if (httpResponse != null) { + httpResponse.release(); + } + } + } + + @Override + public void afterResponseSent(Request request, Response response, ChannelFuture channelFuture) { + if (!HttpUtil.isKeepAlive(((HttpRequest) request).getNettyHttpRequest())) { + channelFuture.addListener(ChannelFutureListener.CLOSE); + } + } + + public byte[] encodeResponseBody(int protocolType, Request request, Response response) { + FullHttpRequest httpRequest = (FullHttpRequest) request.getMsg(); + Object body = makeResponse(protocolType, response); + return encodeBody(protocolType, + httpRequest.headers().get(HttpHeaderNames.CONTENT_ENCODING), + body, response.getRpcMethodInfo()); + } + + @Override + public boolean returnChannelBeforeResponse() { + return false; + } + + @Override + public boolean isCoexistence() { + return true; + } + + public static int parseProtocolType(String contentType) { + String contentType2 = contentType.toLowerCase(); + if (contentType2.equals(HttpRpcProtocol.CONTENT_TYPE_JSON)) { + return Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE; + } else if (contentType2.equals(HttpRpcProtocol.CONTENT_TYPE_PROTOBUF)) { + return Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE; + } else { + LOG.warn("unknown contentType={}", contentType); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "unknown contentType=" + contentType); + } + } + + public String getContentType(Integer protocolType) { + String contentType; + switch (protocolType) { + case Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE: { + contentType = HttpRpcProtocol.CONTENT_TYPE_JSON; + break; + } + case Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE: { + contentType = HttpRpcProtocol.CONTENT_TYPE_PROTOBUF; + break; + } + default: + LOG.warn("unknown protocolType={}", protocolType); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, + "unknown protocolType=" + protocolType); + } + return contentType; + } + + public byte[] encodeBody(int protocolType, String encoding, Object body, RpcMethodInfo rpcMethodInfo) { + byte[] bodyBytes; + try { + switch (protocolType) { + case Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE: { + String bodyJson = ""; + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + jsonPbConverter.print((Message) body, out, Charset.forName(encoding)); + out.flush(); + bodyJson = out.toString(encoding); + } else { + bodyJson = gson.toJson(body); + } + bodyBytes = bodyJson.getBytes(encoding); + break; + } + case Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE: { + if (rpcMethodInfo.getTarget() != null) { + // server端 + bodyBytes = rpcMethodInfo.outputEncode(body); + } else { + bodyBytes = rpcMethodInfo.inputEncode(body); + } + break; + } + default: + LOG.warn("unkown protocolType={}", protocolType); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, + "unkown protocolType=" + protocolType); + } + } catch (Exception ex) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "encode body failed", ex); + } + return bodyBytes; + } + + public Object decodeBody(int protocolType, String encoding, byte[] bytes) { + Object body = null; + try { + switch (protocolType) { + case Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE: { + body = new String(bytes, encoding); + break; + } + case Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE: { + // decode when parse response + body = bytes; + break; + } + default: + LOG.warn("unknown protocolType={}", protocolType); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, + "unknown protocolType=" + protocolType); + } + } catch (Exception ex) { + LOG.error("decodeBody failed", ex); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "decode body failed", ex); + } + return body; + } + + /** + * fill http response headers + * @param fullHttpResponse netty http response + * @param response brpc standard response + * @param fullHttpRequest netty http request + */ + public void addHttpResponseHeaders(FullHttpResponse fullHttpResponse, + Response response, + FullHttpRequest fullHttpRequest) { + boolean keepAlive = HttpUtil.isKeepAlive(fullHttpRequest); + if (keepAlive) { + fullHttpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + } + fullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, + fullHttpRequest.headers().get(HttpHeaderNames.CONTENT_TYPE)); + if (fullHttpRequest.headers().contains("callId")) { + fullHttpResponse.headers().set("callId", fullHttpRequest.headers().get("callId")); + } + if (fullHttpRequest.headers().contains(CORRELATION_ID)) { + fullHttpResponse.headers().set(CORRELATION_ID, fullHttpRequest.headers().get(CORRELATION_ID)); + } + if (response.getKvAttachment() != null) { + for (Map.Entry entry : response.getKvAttachment().entrySet()) { + fullHttpResponse.headers().set(entry.getKey(), entry.getValue()); + } + } + fullHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, fullHttpResponse.content().readableBytes()); + } + + public Object makeRequest(int id, String methodName, Object[] args) { + if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE) { + if (args == null || args.length == 0) { + return null; + } + if (args.length == 1) { + return args[0]; + } else { + return args; + } + } else if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE) { + if (args == null || args.length == 0) { + return null; + } + return args[0]; + + } else { + Map map = new HashMap(); + map.put("jsonrpc", "2.0"); + map.put("method", methodName); + if (args != null) { + map.put("params", args); + } else { + map.put("params", new Object[0]); + } + + map.put("id", "" + id); + return gson.toJsonTree(map); + } + } + + public Object makeResponse(int protocolType, Response response) { + Long id = response.getLogId(); + if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE) { + return response.getResult(); + } else if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE) { + return response.getResult(); + } else { + JsonObject res = new JsonObject(); + JsonElement result = gson.toJsonTree( + response.getResult(), response.getRpcMethodInfo().getMethod().getReturnType()); + res.addProperty("jsonrpc", "2.0"); + if (result != null) { + res.add("result", result); + } else { + res.addProperty("error", "bad request"); + } + if (id != null) { + res.addProperty("id", id.intValue()); + } + + return res; + } + } + + public String buildHttpUri(String serviceName, String methodName) { + // uri格式为 /serviceName/methodName + return "/" + serviceName + "/" + methodName; + } + + // 解析correlationId + public long parseCorrelationId(String headerCorrelationId, Long channelAttachCorrelationId) { + // 以headerCorrelationId为准,headerCorrelationId为null则以channelAttachCorrelationId为准 + if (headerCorrelationId != null) { + return Long.valueOf(headerCorrelationId); + } else if (channelAttachCorrelationId != null) { + return channelAttachCorrelationId; + } + return -1; + } + + public Object parseHttpResponse(Object body, RpcMethodInfo rpcMethodInfo) { + Object response; + try { + switch (protocolType) { + case Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE: + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ProtobufRpcMethodInfo protobufRpcMethodInfo = (ProtobufRpcMethodInfo) rpcMethodInfo; + Message.Builder rspBuilder = protobufRpcMethodInfo.getOutputInstance().newBuilderForType(); + jsonPbConverter.merge((String) body, ExtensionRegistry.getEmptyRegistry(), rspBuilder); + response = rspBuilder.build(); + } else { + response = gson.fromJson((String) body, rpcMethodInfo.getOutputClass()); + } + break; + case Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE: + response = rpcMethodInfo.outputDecode((byte[]) body); + break; + default: + LOG.warn("unknown protocolType={}", protocolType); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, + "unknown protocolType=" + protocolType); + } + } catch (Exception ex) { + LOG.error("parse rpc response error", ex); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "parse rpc response error", ex); + } + return response; + } + + public Object[] parseRequestParam(int protocolType, Object body, RpcMethodInfo rpcMethodInfo) { + if (body == null) { + return null; + } + + Object[] args = new Object[rpcMethodInfo.getInputClasses().length]; + if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_JSON_VALUE) { + try { + if (rpcMethodInfo instanceof ProtobufRpcMethodInfo) { + ProtobufRpcMethodInfo protobufRpcMethodInfo = (ProtobufRpcMethodInfo) rpcMethodInfo; + Message.Builder argBuilder = protobufRpcMethodInfo.getInputInstance().newBuilderForType(); + jsonPbConverter.merge((String) body, ExtensionRegistry.getEmptyRegistry(), argBuilder); + args[0] = argBuilder.build(); + } else { + if (rpcMethodInfo.getInputClasses().length == 1) { + args[0] = gson.fromJson((String) body, rpcMethodInfo.getInputClasses()[0]); + } else { + JsonArray jsonArray = (JsonArray) jsonParser.parse((String) body); + int jsonSize = jsonArray.size(); + if (jsonSize != rpcMethodInfo.getInputClasses().length) { + LOG.warn("bad params num"); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "bad params num"); + } + for (int i = 0; i < jsonSize; i++) { + args[i] = gson.fromJson(jsonArray.get(i), rpcMethodInfo.getInputClasses()[i]); + } + } + } + } catch (Exception e) { + LOG.error("decodeBody failed", e); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "decode body failed", e); + } + } else if (protocolType == Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE) { + Object requestMessage = null; + try { + requestMessage = rpcMethodInfo.inputDecode((byte[]) body); + } catch (Exception ex) { + LOG.error("invoke protobuf method error, ex : ", ex); + return null; + } + args[0] = requestMessage; + } else { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "unknown protocol"); + } + + return args; + + } + +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcServlet.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcServlet.java new file mode 100644 index 00000000..a885c118 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/http/HttpRpcServlet.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http; + +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.HttpResponse; +import com.baidu.brpc.protocol.*; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.spi.ExtensionLoaderManager; +import io.netty.handler.codec.http.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; + +/** + * 在paas场景下部署时,bns会绑定到主端口上。 + * 如果以servlet方式提供baidu json rpc协议的服务, + * client端就可以通过bns访问http服务。 + */ +public class HttpRpcServlet extends HttpServlet { + + private static final Logger LOG = LoggerFactory.getLogger(HttpRpcServlet.class); + + public void registerService(Object service) { + ServiceManager serviceManager = ServiceManager.getInstance(); + serviceManager.registerService(service, null); + } + + public void registerService(Class targetClass, Object service) { + ServiceManager serviceManager = ServiceManager.getInstance(); + serviceManager.registerService(targetClass, service, null); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + long startTime = System.nanoTime(); + String requestUri = req.getRequestURI(); + if (requestUri == null) { + LOG.warn("invalid request"); + resp.setStatus(404); + return; + } + + String encoding = req.getCharacterEncoding(); + String contentType = req.getContentType().split(";")[0]; + if (contentType == null) { + contentType = "application/baidu.json-rpc"; + } else { + contentType = contentType.toLowerCase(); + } + + byte[] bytes = this.readStream(req.getInputStream(), req.getContentLength()); + + FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, requestUri); + httpRequest.headers().add(HttpHeaderNames.CONTENT_TYPE, contentType); + httpRequest.content().writeBytes(bytes); + int protocolType = HttpRpcProtocol.parseProtocolType(contentType); + ExtensionLoaderManager.getInstance().loadAllExtensions(encoding); + Protocol protocol = ProtocolManager.getInstance().getProtocol(protocolType); + Request request = null; + Response response = new HttpResponse(); + String errorMsg = null; + try { + request = protocol.decodeRequest(httpRequest); + Object result = request.getTargetMethod().invoke(request.getTarget(), request.getArgs()); + response.setResult(result); + response.setRpcMethodInfo(request.getRpcMethodInfo()); + response.setLogId(request.getLogId()); + response.setCorrelationId(request.getCorrelationId()); + protocol.encodeResponse(request, response); + } catch (Exception ex) { + errorMsg = String.format("invoke method failed, msg=%s", ex.getMessage()); + LOG.error(errorMsg); + response.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + } + + resp.setContentType(contentType); + resp.setCharacterEncoding(encoding); + if (errorMsg == null) { + byte[] content = ((HttpRpcProtocol) protocol).encodeResponseBody(protocolType, request, response); + resp.setContentLength(content.length); + resp.getOutputStream().write(content); + } else { + byte[] content = errorMsg.getBytes(); + resp.setContentLength(content.length); + resp.getOutputStream().write(content); + } + + if (request != null) { + long endTime = System.nanoTime(); + LOG.debug("uri={} logId={} service={} method={} elapseNs={}", + requestUri, + request.getLogId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName(), + endTime - startTime); + } + + } + + private byte[] readStream(InputStream input, int length) throws IOException { + byte[] bytes = new byte[length]; + + int bytesRead; + for (int offset = 0; offset < bytes.length; offset += bytesRead) { + bytesRead = input.read(bytes, offset, bytes.length - offset); + if (bytesRead == -1) { + break; + } + } + + return bytes; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcDecodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcDecodePacket.java new file mode 100644 index 00000000..36048fe8 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcDecodePacket.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.hulu; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Setter +@Getter +public class HuluRpcDecodePacket { + private ByteBuf metaBuf; + private ByteBuf protoAndAttachmentBuf; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcEncodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcEncodePacket.java new file mode 100644 index 00000000..b11238bb --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcEncodePacket.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.hulu; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class HuluRpcEncodePacket { + private HuluRpcProto.HuluRpcRequestMeta requestMeta; + private HuluRpcProto.HuluRpcResponseMeta responseMeta; + private ByteBuf proto; + private ByteBuf attachment; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocol.java new file mode 100644 index 00000000..682e0237 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocol.java @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.hulu; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.compress.Compress; +import com.baidu.brpc.compress.CompressManager; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.BaiduRpcErrno; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ProtobufUtils; +import com.baidu.brpc.utils.RpcMetaUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; + +/** + * Notes on HULU PBRPC Protocol: + *
    + *
  • Header format is ["HULU"][body_size][meta_size + * ], 12 bytes in total + *
  • + *
  • {@code body_size} and {@code meta_size} are NOT in + * network byte order (little endian) + *
  • + *
  • Use service->name() and method_index to identify the service and + * method to call
  • + *
  • {@code user_message_size} is set iff request/response has attachment + *
  • + *
  • The following fields of rpc are not supported yet: + *
    • chunk_info
    + *
  • + *
+ */ +public class HuluRpcProtocol extends AbstractProtocol { + private static final Logger LOG = LoggerFactory.getLogger(HuluRpcProtocol.class); + private static final byte[] MAGIC_HEAD = "HULU".getBytes(); + private static final int FIXED_LEN = 12; + private static final HuluRpcProto.HuluRpcRequestMeta defaultRpcRequestMetaInstance = + HuluRpcProto.HuluRpcRequestMeta.getDefaultInstance(); + private static final HuluRpcProto.HuluRpcResponseMeta defaultRpcResponseMetaInstance = + HuluRpcProto.HuluRpcResponseMeta.getDefaultInstance(); + private static final CompressManager compressManager = CompressManager.getInstance(); + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + HuluRpcEncodePacket requestPacket = new HuluRpcEncodePacket(); + HuluRpcProto.HuluRpcRequestMeta.Builder metaBuilder = HuluRpcProto.HuluRpcRequestMeta.newBuilder(); + metaBuilder.setCorrelationId(request.getCorrelationId()); + metaBuilder.setLogId(request.getLogId()); + int compressType = request.getCompressType(); + metaBuilder.setCompressType(compressType); + + // service method + RpcMetaUtils.RpcMetaInfo rpcMetaInfo = RpcMetaUtils.parseRpcMeta(request.getTargetMethod()); + metaBuilder.setServiceName(rpcMetaInfo.getServiceName()); + try { + int methodIndex = Integer.valueOf(rpcMetaInfo.getMethodName()); + metaBuilder.setMethodIndex(methodIndex); + } catch (NumberFormatException ex) { + String errorMsg = "methodName must be integer when using hulu rpc, " + + "it is equal to proto method sequence from 0"; + LOG.warn(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg, ex); + } + + if (request.getTraceId() != null) { + metaBuilder.setTraceId(request.getTraceId()); + } + if (request.getSpanId() != null) { + metaBuilder.setSpanId(request.getSpanId()); + } + if (request.getParentSpanId() != null) { + metaBuilder.setSpanId(request.getParentSpanId()); + } + if (request.getKvAttachment() != null) { + for (Map.Entry kv : request.getKvAttachment().entrySet()) { + metaBuilder.addExtFieldsBuilder().setKey(kv.getKey()).setValue((String) kv.getValue()); + } + } + + // proto + Object proto = request.getArgs()[0]; + Compress compress = compressManager.getCompress(compressType); + ByteBuf protoBuf = compress.compressInput(proto, request.getRpcMethodInfo()); + requestPacket.setProto(protoBuf); + + // attachement + if (request.getBinaryAttachment() != null + && request.getBinaryAttachment().isReadable()) { + requestPacket.setAttachment(request.getBinaryAttachment()); + metaBuilder.setUserMessageSize(protoBuf.readableBytes()); + } + requestPacket.setRequestMeta(metaBuilder.build()); + return encode(requestPacket); + } + + @Override + public Response decodeResponse(Object packet, ChannelHandlerContext ctx) throws Exception { + HuluRpcDecodePacket responsePacket = (HuluRpcDecodePacket) packet; + ByteBuf metaBuf = responsePacket.getMetaBuf(); + ByteBuf protoAndAttachmentBuf = responsePacket.getProtoAndAttachmentBuf(); + ByteBuf protoBuf = null; + try { + RpcResponse rpcResponse = new RpcResponse(); + HuluRpcProto.HuluRpcResponseMeta responseMeta = (HuluRpcProto.HuluRpcResponseMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcResponseMetaInstance); + Long correlationId = responseMeta.getCorrelationId(); + rpcResponse.setCorrelationId(correlationId); + + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + int compressType = responseMeta.getCompressType(); + rpcResponse.setCompressType(compressType); + try { + if (responseMeta != null && responseMeta.getErrorCode() == 0) { + Compress compress = compressManager.getCompress(compressType); + if (responseMeta.getUserMessageSize() > 0) { + protoBuf = protoAndAttachmentBuf.slice( + protoAndAttachmentBuf.readerIndex(), + responseMeta.getUserMessageSize()); + } else { + protoBuf = protoAndAttachmentBuf; + } + Object responseProto = compress.uncompressOutput(protoBuf, future.getRpcMethodInfo()); + rpcResponse.setResult(responseProto); + + // attachment + if (responseMeta.getUserMessageSize() > 0) { + rpcResponse.setBinaryAttachment(protoAndAttachmentBuf); + responsePacket.setProtoAndAttachmentBuf(null); + } + } else { + rpcResponse.setException(new RpcException( + RpcException.SERVICE_EXCEPTION, responseMeta.getErrorText())); + } + } catch (Exception ex) { + // 解析失败直接抛异常 + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "decode response failed", ex); + } + return rpcResponse; + } finally { + if (responsePacket.getMetaBuf() != null) { + responsePacket.getMetaBuf().release(); + } + if (responsePacket.getProtoAndAttachmentBuf() != null) { + responsePacket.getProtoAndAttachmentBuf().release(); + } + } + + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.createRequest(); + HuluRpcDecodePacket requestPacket = (HuluRpcDecodePacket) packet; + ByteBuf metaBuf = requestPacket.getMetaBuf(); + ByteBuf protoAndAttachmentBuf = requestPacket.getProtoAndAttachmentBuf(); + ByteBuf protoBuf = null; + try { + HuluRpcProto.HuluRpcRequestMeta requestMeta = (HuluRpcProto.HuluRpcRequestMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcRequestMetaInstance); + request.setCorrelationId(requestMeta.getCorrelationId()); + request.setLogId(requestMeta.getLogId()); + int compressType = requestMeta.getCompressType(); + request.setCompressType(compressType); + + // service info + ServiceManager serviceManager = ServiceManager.getInstance(); + RpcMethodInfo rpcMethodInfo = serviceManager.getService( + requestMeta.getServiceName(), String.valueOf(requestMeta.getMethodIndex())); + if (rpcMethodInfo == null) { + String errorMsg = String.format("Fail to find service=%s, methodIndex=%s", + requestMeta.getServiceName(), requestMeta.getMethodIndex()); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + return request; + } + if (requestMeta.hasTraceId()) { + request.setTraceId(requestMeta.getTraceId()); + } + if (requestMeta.hasSpanId()) { + request.setSpanId(request.getSpanId()); + } + if (requestMeta.hasParentSpanId()) { + request.setParentSpanId(requestMeta.getParentSpanId()); + } + if (requestMeta.getExtFieldsCount() > 0) { + if (request.getKvAttachment() == null) { + request.setKvAttachment(new HashMap()); + } + for (HuluRpcProto.HuluRpcRequestMetaExtField extField : requestMeta.getExtFieldsList()) { + request.getKvAttachment().put(extField.getKey(), extField.getValue()); + } + } + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setTarget(rpcMethodInfo.getTarget()); + + // proto body + try { + Compress compress = compressManager.getCompress(compressType); + int userMessageSize = requestMeta.getUserMessageSize(); + if (userMessageSize > 0) { + protoBuf = protoAndAttachmentBuf.slice( + protoAndAttachmentBuf.readerIndex(), + userMessageSize); + } else { + protoBuf = protoAndAttachmentBuf; + } + Object requestProto = compress.uncompressInput(protoBuf, rpcMethodInfo); + request.setArgs(new Object[] {requestProto}); + // attachment + if (userMessageSize > 0) { + request.setBinaryAttachment(protoAndAttachmentBuf); + protoAndAttachmentBuf = null; + } + } catch (Exception ex) { + String errorMsg = String.format("decode failed, msg=%s", ex.getMessage()); + LOG.error(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg, ex); + } + return request; + } finally { + if (metaBuf != null) { + metaBuf.release(); + } + if (protoAndAttachmentBuf != null) { + protoAndAttachmentBuf.release(); + } + } + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + HuluRpcEncodePacket responsePacket = new HuluRpcEncodePacket(); + HuluRpcProto.HuluRpcResponseMeta.Builder metaBuilder = HuluRpcProto.HuluRpcResponseMeta.newBuilder(); + metaBuilder.setCorrelationId(response.getCorrelationId()); + int compressType = response.getCompressType(); + metaBuilder.setCompressType(compressType); + + if (response.getException() != null) { + metaBuilder.setErrorCode(BaiduRpcErrno.Errno.EINTERNAL_VALUE); + if (StringUtils.isNotBlank(response.getException().getMessage())) { + metaBuilder.setErrorText(response.getException().getMessage()); + } + responsePacket.setResponseMeta(metaBuilder.build()); + } else { + metaBuilder.setErrorCode(0); + Compress compress = compressManager.getCompress(compressType); + ByteBuf responseProtoBuf = compress.compressOutput( + response.getResult(), response.getRpcMethodInfo()); + responsePacket.setProto(responseProtoBuf); + + // attachment + if (response.getBinaryAttachment() != null) { + responsePacket.setAttachment(response.getBinaryAttachment()); + metaBuilder.setUserMessageSize(responseProtoBuf.readableBytes()); + } + responsePacket.setResponseMeta(metaBuilder.build()); + } + + return encode(responsePacket); + } + + protected ByteBuf encode(HuluRpcEncodePacket packet) throws IOException { + int metaSize; + ByteBuf metaBuf; + + HuluRpcProto.HuluRpcRequestMeta requestMeta = packet.getRequestMeta(); + if (requestMeta != null) { + // request + byte[] metaBytes = requestMeta.toByteArray(); + metaSize = metaBytes.length; + metaBuf = Unpooled.wrappedBuffer(metaBytes); + } else { + // response + byte[] metaBytes = packet.getResponseMeta().toByteArray(); + metaSize = metaBytes.length; + metaBuf = Unpooled.wrappedBuffer(metaBytes); + } + + // fixed header buf + ByteBuf headerBuf = Unpooled.buffer(FIXED_LEN); + headerBuf.writeBytes(MAGIC_HEAD); + int bodySize = metaSize; + ByteBuf protoBuf = packet.getProto(); + if (protoBuf != null) { + bodySize += protoBuf.readableBytes(); + } + ByteBuf attachmentBuf = packet.getAttachment(); + if (attachmentBuf != null) { + bodySize += attachmentBuf.readableBytes(); + } + headerBuf.writeIntLE(bodySize); + headerBuf.writeIntLE(metaSize); + + if (protoBuf != null && attachmentBuf != null) { + return Unpooled.wrappedBuffer(headerBuf, metaBuf, protoBuf, attachmentBuf); + } else if (protoBuf != null) { + return Unpooled.wrappedBuffer(headerBuf, metaBuf, protoBuf); + } else { + return Unpooled.wrappedBuffer(headerBuf, metaBuf); + } + } + + @Override + public HuluRpcDecodePacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < FIXED_LEN) { + throw notEnoughDataException; + } + ByteBuf fixHeaderBuf = in.retainedSlice(FIXED_LEN); + + try { + byte[] magic = new byte[4]; + fixHeaderBuf.readBytes(magic); + if (!Arrays.equals(magic, MAGIC_HEAD)) { + throw new BadSchemaException("not valid magic head for hulu"); + } + int bodySize = fixHeaderBuf.readIntLE(); + int metaSize = fixHeaderBuf.readIntLE(); + // 512M + if (bodySize > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodySize); + } + if (in.readableBytes() < FIXED_LEN + bodySize) { + throw notEnoughDataException; + } + + in.skipBytes(FIXED_LEN); + HuluRpcDecodePacket packet = new HuluRpcDecodePacket(); + try { + // meta + ByteBuf metaBuf = in.readRetainedSlice(metaSize); + packet.setMetaBuf(metaBuf); + + // body + ByteBuf protoAndAttachmentBuf = in.readRetainedSlice(bodySize - metaSize); + packet.setProtoAndAttachmentBuf(protoAndAttachmentBuf); + + return packet; + } catch (Exception ex) { + LOG.warn("decode failed, ex={}", ex.getMessage()); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex); + } + } finally { + fixHeaderBuf.release(); + } + } + + @Override + public boolean isCoexistence() { + return true; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocolFactory.java new file mode 100644 index 00000000..fa44882f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/hulu/HuluRpcProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.hulu; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class HuluRpcProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_HULU_PBRPC_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new HuluRpcProtocol(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHead.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHead.java new file mode 100644 index 00000000..c4868cfa --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHead.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.exceptions.BadSchemaException; +import io.netty.buffer.ByteBuf; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * * ns产品线网络交互统一的包头,注释包含为(M)的为必须遵循的规范 + * + *
+ *     typedef struct _nshead_t
+ *     {
+ *         unsigned short id;              ///
+ * 

+ * 2+2+4+16+4+4+4=36 byte in total. + */ +public class NSHead { + + public static final int NSHEAD_LENGTH = 36; + public static final int NSHEAD_MAGIC_NUM = 0xfb709394; + public static final int PROVIDER_LENGTH = 16; + + private static final byte[] ZEROS = new byte[PROVIDER_LENGTH]; + + public short id = 0x00; + + public short version = 0x01; + + public int logId; + + public String provider = ""; + + public int magicNumber = NSHEAD_MAGIC_NUM; + + public int reserved = 0; + + public int bodyLength = 0; + + public NSHead(int logId, short id, short version, String provider, int bodyLength) { + this.logId = logId; + this.id = id; + this.version = version; + if (provider != null) { + this.provider = provider; + } + this.bodyLength = bodyLength; + } + + public NSHead(int logId, int bodyLength) { + this.logId = logId; + this.bodyLength = bodyLength; + } + + public NSHead() { + } + + public static NSHead fromByteBuf(ByteBuf buf) throws BadSchemaException { + NSHead head = new NSHead(); + if (buf.readableBytes() < NSHEAD_LENGTH) { + throw new IllegalArgumentException("not enough bytes to read"); + } + head.id = buf.readShortLE(); + head.version = buf.readShortLE(); + head.logId = buf.readIntLE(); + byte[] bytes = new byte[PROVIDER_LENGTH]; + buf.readBytes(bytes); + int n = 0; + while (n < bytes.length && bytes[n] != 0) { + n++; + } + head.provider = new String(bytes, 0, n); + head.magicNumber = buf.readIntLE(); + if (head.magicNumber != NSHEAD_MAGIC_NUM) { + throw new BadSchemaException("nshead magic number does not match"); + } + head.reserved = buf.readIntLE(); + head.bodyLength = buf.readIntLE(); + return head; + } + + public byte[] toBytes() { + ByteBuffer buf = ByteBuffer.allocate(NSHEAD_LENGTH); + buf.order(ByteOrder.LITTLE_ENDIAN); + buf.putShort(id); + buf.putShort(version); + buf.putInt(logId); + byte[] providerBytes = provider.getBytes(); + if (providerBytes.length >= PROVIDER_LENGTH) { + buf.put(providerBytes, 0, PROVIDER_LENGTH); + } else { + buf.put(providerBytes, 0, providerBytes.length); + buf.put(ZEROS, 0, PROVIDER_LENGTH - providerBytes.length); + } + buf.putInt(magicNumber); + buf.putInt(reserved); + buf.putInt(bodyLength); + return buf.array(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(id).append(version).append(logId).append(magicNumber).append(reserved) + .append(bodyLength).toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof NSHead)) { + return false; + } + NSHead other = (NSHead) obj; + return new EqualsBuilder().append(id, other.id).append(version, other.version).append(logId, other.logId) + .append(reserved, other.reserved).append(bodyLength, other.bodyLength).isEquals(); + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("id", Integer.toHexString(id)) + .append("version", Integer.toHexString(version)) + .append("logId", Long.toHexString(logId) + "(" + logId + ")").append("provider", provider) + .append("magicNumber", Integer.toHexString(magicNumber)) + .append("reserved", Integer.toHexString(reserved)) + .append("bodyLength", Integer.toHexString(bodyLength)).toString(); + } + + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocol.java new file mode 100644 index 00000000..6cb1c5af --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocol.java @@ -0,0 +1,65 @@ +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.exceptions.RpcException; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.netty.buffer.ByteBuf; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.Validate; + +@Slf4j +public class NSHeadJsonProtocol extends NSHeadRpcProtocol { + + private static final Gson gson = (new GsonBuilder()) + .disableHtmlEscaping() + .serializeSpecialFloatingPointValues() + .create(); + + public NSHeadJsonProtocol(String encoding) { + super(encoding); + } + + @Override + public byte[] encodeBody(Object body, RpcMethodInfo rpcMethodInfo) { + Validate.notNull(body, "body must not be empty"); + byte[] bytes; + String json = gson.toJson(body); + try { + bytes = json.getBytes(this.encoding); + } catch (Exception e) { + log.error("can not serialize object using mcpack", e); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e); + } + + return bytes; + } + + @Override + public Object decodeBody(ByteBuf bodyBuf, RpcMethodInfo rpcMethodInfo) { + try { + Object result; + try { + int readableBytes = bodyBuf.readableBytes(); + byte[] bodyBytes = new byte[readableBytes]; + bodyBuf.readBytes(bodyBytes); + String jsonString = new String(bodyBytes, this.encoding); + if (rpcMethodInfo.getTarget() != null) { + // server端 + result = gson.fromJson(jsonString, rpcMethodInfo.getInputClasses()[0]); + } else { + result = gson.fromJson(jsonString, rpcMethodInfo.getOutputClass()); + } + } catch (Exception e) { + log.error("can not deserialize object", e); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e); + } + return result; + } finally { + if (bodyBuf != null) { + bodyBuf.release(); + } + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocolFactory.java new file mode 100644 index 00000000..c42dd338 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadJsonProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class NSHeadJsonProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_NSHEAD_JSON_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new NSHeadJsonProtocol(encoding); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadMeta.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadMeta.java new file mode 100644 index 00000000..59b43c40 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadMeta.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface NSHeadMeta { + + /** + * provider + * @return + */ + String provider() default ""; + + /** + * id + * @return + */ + short id() default 0x00; + + /** + * version + * @return + */ + short version() default 0x01; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadPacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadPacket.java new file mode 100644 index 00000000..0fa36b6f --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadPacket.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class NSHeadPacket { + private NSHead nsHead; // nsHead请求头 + private ByteBuf bodyBuf; // body +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocol.java new file mode 100644 index 00000000..9f56c779 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocol.java @@ -0,0 +1,59 @@ +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.exceptions.RpcException; +import io.netty.buffer.ByteBuf; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.Validate; + +import java.io.IOException; + +@Slf4j +public class NSHeadProtobufProtocol extends NSHeadRpcProtocol { + + public NSHeadProtobufProtocol(String encoding) { + super(encoding); + } + + @Override + public byte[] encodeBody(Object body, RpcMethodInfo rpcMethodInfo) { + Validate.notNull(body, "body must not be empty"); + byte[] bytes; + try { + if (rpcMethodInfo.getTarget() != null) { + // server端,所以是encode response + bytes = rpcMethodInfo.outputEncode(body); + } else { + bytes = rpcMethodInfo.inputEncode(body); + } + } catch (IOException ex) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex); + } + + return bytes; + } + + @Override + public Object decodeBody(ByteBuf bodyBuf, RpcMethodInfo rpcMethodInfo) { + try { + Object result; + try { + if (rpcMethodInfo.getTarget() != null) { + // server端,所以是decode request + result = rpcMethodInfo.inputDecode(bodyBuf); + } else { + result = rpcMethodInfo.outputDecode(bodyBuf); + } + } catch (IOException e) { + log.warn("invoke parseFrom method error", e); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e); + } + return result; + } finally { + if (bodyBuf != null) { + bodyBuf.release(); + } + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocolFactory.java new file mode 100644 index 00000000..585c2714 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadProtobufProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class NSHeadProtobufProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new NSHeadProtobufProtocol(encoding); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadRpcProtocol.java new file mode 100644 index 00000000..3c1df4ca --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/nshead/NSHeadRpcProtocol.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import java.util.Map; + +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.server.ServiceManager; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; + +/** + * nshead based protocol, the header format is {@link NSHead} + */ +@SuppressWarnings("unchecked") +public abstract class NSHeadRpcProtocol extends AbstractProtocol { + private static final Logger LOG = LoggerFactory.getLogger(NSHeadRpcProtocol.class); + protected String encoding = "utf-8"; + + public NSHeadRpcProtocol(String encoding) { + if (encoding != null) { + this.encoding = encoding; + } + } + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + Validate.notEmpty(request.getArgs(), "args must not be empty"); + byte[] bodyBytes = encodeBody(request.getArgs()[0], request.getRpcMethodInfo()); + NSHead nsHead = request.getNsHead(); + nsHead.bodyLength = bodyBytes.length; + byte[] nsHeadBytes = nsHead.toBytes(); + return Unpooled.wrappedBuffer(nsHeadBytes, bodyBytes); + } + + @Override + public Response decodeResponse(Object in, ChannelHandlerContext ctx) throws Exception { + NSHeadPacket packet = (NSHeadPacket) in; + RpcResponse rpcResponse = new RpcResponse(); + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + Long correlationId = channelInfo.getCorrelationId(); + rpcResponse.setCorrelationId(correlationId); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + + Object responseBody = decodeBody(packet.getBodyBuf(), future.getRpcMethodInfo()); + if (responseBody == null) { + return null; + } + + rpcResponse.setResult(responseBody); + return rpcResponse; + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + byte[] bodyBytes = encodeBody(response.getResult(), response.getRpcMethodInfo()); + NSHead nsHead = new NSHead((int) response.getLogId(), bodyBytes.length); + byte[] headBytes = nsHead.toBytes(); + return Unpooled.wrappedBuffer(headBytes, bodyBytes); + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.createRequest(); + NSHeadPacket nsHeadPacket = (NSHeadPacket) packet; + request.setLogId((long) nsHeadPacket.getNsHead().logId); + + ServiceManager serviceManager = ServiceManager.getInstance(); + Map serviceInfoMap = serviceManager.getServiceMap(); + if (serviceInfoMap.size() == 0) { + String errMsg = "serviceInfoMap == 0"; + LOG.error(errMsg); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errMsg)); + return request; + } + // 因为nshead的服务只会有一个接口,一个方法,所以这里只需要取第一个方法即可 + RpcMethodInfo rpcMethodInfo = serviceInfoMap.entrySet().iterator().next().getValue(); + if (rpcMethodInfo == null) { + String errMsg = "serviceInfo is null in server"; + LOG.error(errMsg); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errMsg)); + return request; + } + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + request.setRpcMethodInfo(rpcMethodInfo); + + Object body = decodeBody(nsHeadPacket.getBodyBuf(), rpcMethodInfo); + request.setTarget(rpcMethodInfo.getTarget()); + request.setArgs(new Object[] {body}); + request.setTargetMethod(rpcMethodInfo.getMethod()); + return request; + } + + @Override + public boolean returnChannelBeforeResponse() { + return false; + } + + @Override + public NSHeadPacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < NSHead.NSHEAD_LENGTH) { + throw notEnoughDataException; + } + NSHeadPacket packet = new NSHeadPacket(); + ByteBuf fixHeaderBuf = in.retainedSlice(NSHead.NSHEAD_LENGTH); + try { + NSHead nsHead = NSHead.fromByteBuf(fixHeaderBuf); + packet.setNsHead(nsHead); + int bodyLength = nsHead.bodyLength; + + // 512M + if (bodyLength > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodyLength); + } + + if (in.readableBytes() < NSHead.NSHEAD_LENGTH + bodyLength) { + throw notEnoughDataException; + } + + in.skipBytes(NSHead.NSHEAD_LENGTH); + ByteBuf bodyBuf = in.readRetainedSlice(bodyLength); + packet.setBodyBuf(bodyBuf); + return packet; + } finally { + fixHeaderBuf.release(); + } + } + + public abstract byte[] encodeBody(Object body, RpcMethodInfo rpcMethodInfo); + + public abstract Object decodeBody(ByteBuf bodyBuf, RpcMethodInfo rpcMethodInfo); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcPacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcPacket.java new file mode 100644 index 00000000..e1335143 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcPacket.java @@ -0,0 +1,14 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.protocol.nshead.NSHead; +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PublicPbRpcPacket { + + private NSHead nsHead; + private ByteBuf body; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcProtocolFactory.java new file mode 100644 index 00000000..ae50d3b6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbRpcProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class PublicPbRpcProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_PUBLIC_PBRPC_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new PublicPbrpcProtocol(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocol.java new file mode 100644 index 00000000..4c39ff31 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocol.java @@ -0,0 +1,293 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.compress.Compress; +import com.baidu.brpc.compress.CompressManager; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.BaiduRpcErrno; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.PublicPbrpcRequest; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.PublicPbrpcResponse; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.RequestBody; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.RequestHead; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.ResponseBody; +import com.baidu.brpc.protocol.pbrpc.PublicPbrpcProto.ResponseHead; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ProtobufUtils; +import com.baidu.brpc.utils.RpcMetaUtils; +import com.google.protobuf.ByteString; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; +import org.apache.tools.ant.util.DateUtils; + +import java.net.InetAddress; +import java.util.Calendar; + +@Slf4j +public class PublicPbrpcProtocol extends AbstractProtocol { + + private static final String VERSION = "pbrpc=1.0"; + private static final String CHARSET = "utf-8"; + private static final String SUCCESS_TEXT = "success"; + private static final String TIME_FORMAT = "%Y%m%d%H%M%S"; + private static final String PROVIDER = "__pbrpc__"; + private static final int CONTENT_TYPE = 1; + private static final int COMPRESS_TYPE = 1; + private static final int NSHEAD_VERSION = 1000; + + private static final CompressManager compressManager = CompressManager.getInstance(); + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + + // service method + RpcMetaUtils.RpcMetaInfo rpcMetaInfo = RpcMetaUtils.parseRpcMeta(request.getTargetMethod()); + int methodIndex; + try { + methodIndex = Integer.valueOf(rpcMetaInfo.getMethodName()); + } catch (NumberFormatException ex) { + String errorMsg = "methodName must be integer when using pbrpc, " + + "it is equal to proto method sequence from 0"; + log.warn(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg, ex); + } + + // build head + RequestHead.Builder headBuilder = RequestHead.newBuilder(); + headBuilder.setFromHost(InetAddress.getLocalHost().getHostAddress()); + headBuilder.setContentType(CONTENT_TYPE); + // todo short connection + headBuilder.setConnection(false); + headBuilder.setCharset(CHARSET); + headBuilder.setCreateTime(DateUtils.format(Calendar.getInstance().getTime(), TIME_FORMAT)); + headBuilder.setLogId(request.getLogId()); + headBuilder.setCompressType(request.getCompressType()); + + // build body + RequestBody.Builder bodyBuilder = RequestBody.newBuilder(); + bodyBuilder.setVersion(VERSION); + bodyBuilder.setCharset(CHARSET); + bodyBuilder.setService(request.getServiceName()); + bodyBuilder.setMethodId(methodIndex); + bodyBuilder.setId(request.getCorrelationId()); + + Compress compress = compressManager.getCompress(request.getCompressType()); + ByteBuf protoBuf = compress.compressInput(request.getArgs()[0], request.getRpcMethodInfo()); + bodyBuilder.setSerializedRequest(ByteString.copyFrom(protoBuf.nioBuffer())); + + PublicPbrpcRequest pbreq = PublicPbrpcRequest.newBuilder() + .setRequestHead(headBuilder.build()) + .addRequestBody(bodyBuilder.build()) + .build(); + + NSHead nsHead = new NSHead(); + nsHead.logId = (int) request.getLogId(); + nsHead.magicNumber = NSHead.NSHEAD_MAGIC_NUM; + nsHead.provider = PROVIDER; + nsHead.version = NSHEAD_VERSION; + nsHead.bodyLength = pbreq.getSerializedSize(); + + byte[] nsHeadBytes = nsHead.toBytes(); + return Unpooled.wrappedBuffer(nsHeadBytes, request.getRpcMethodInfo().inputEncode(pbreq)); + + } + + + @Override + public PublicPbRpcPacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, + boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < NSHead.NSHEAD_LENGTH) { + throw notEnoughDataException; + } + PublicPbRpcPacket packet = new PublicPbRpcPacket(); + ByteBuf fixHeaderBuf = in.retainedSlice(NSHead.NSHEAD_LENGTH); + try { + NSHead nsHead = NSHead.fromByteBuf(fixHeaderBuf); + packet.setNsHead(nsHead); + int bodyLength = nsHead.bodyLength; + + // 512M + if (bodyLength > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodyLength); + } + + if (in.readableBytes() < NSHead.NSHEAD_LENGTH + bodyLength) { + throw notEnoughDataException; + } + + in.skipBytes(NSHead.NSHEAD_LENGTH); + ByteBuf bodyBuf = in.readRetainedSlice(bodyLength); + packet.setBody(bodyBuf); + return packet; + } finally { + fixHeaderBuf.release(); + } + } + + + @Override + public Response decodeResponse(Object in, ChannelHandlerContext ctx) throws Exception { + PublicPbRpcPacket packet = (PublicPbRpcPacket) in; + + RpcResponse rpcResponse = new RpcResponse(); + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + + ByteBuf bodyBuf = packet.getBody(); + try { + PublicPbrpcResponse pbResponse = (PublicPbrpcResponse) ProtobufUtils.parseFrom(bodyBuf, + PublicPbrpcResponse.getDefaultInstance()); + + ResponseBody body = pbResponse.getResponseBody(0); + ResponseHead head = pbResponse.getResponseHead(); + + if (head.getCode() != 0) { + rpcResponse.setException(new RpcException(head.getText())); + } else { + + rpcResponse.setCorrelationId(body.getId()); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + + Object responseBody; + int compressType = head.getCompressType(); + try { + Compress compress = compressManager.getCompress(compressType); + responseBody = compress.uncompressOutput(body.getSerializedResponse().toByteArray(), + future.getRpcMethodInfo()); + + } catch (Exception ex) { + String errorMsg = String.format("decode failed, msg=%s", ex.getMessage()); + log.error(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg, ex); + } + + rpcResponse.setResult(responseBody); + } + + } finally { + if (bodyBuf != null) { + bodyBuf.release(); + } + } + + return rpcResponse; + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.getRequest(); + + PublicPbRpcPacket pbPacket = (PublicPbRpcPacket) packet; + ByteBuf bodyBuf = pbPacket.getBody(); + try { + PublicPbrpcRequest pbRequest = (PublicPbrpcRequest) ProtobufUtils.parseFrom(bodyBuf, + PublicPbrpcRequest.getDefaultInstance()); + + RequestBody body = pbRequest.getRequestBody(0); + RequestHead head = pbRequest.getRequestHead(); + + request.setCorrelationId(body.getId()); + request.setLogId(head.getLogId()); + int compressType = head.getCompressType(); + request.setCompressType(compressType); + + // service info + ServiceManager serviceManager = ServiceManager.getInstance(); + RpcMethodInfo rpcMethodInfo = serviceManager.getService(body.getService(), + String.valueOf(body.getMethodId())); + if (rpcMethodInfo == null) { + String errorMsg = String.format("Fail to find service=%s, methodIndex=%s", body.getService(), + body.getMethodId()); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + return request; + } + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setTarget(rpcMethodInfo.getTarget()); + + // proto body + try { + Compress compress = compressManager.getCompress(compressType); + Object requestProto = compress.uncompressInput(body.getSerializedRequest().toByteArray(), + rpcMethodInfo); + request.setArgs(new Object[] {requestProto}); + + } catch (Exception ex) { + String errorMsg = String.format("decode failed, msg=%s", ex.getMessage()); + log.error(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg, ex); + } + return request; + } finally { + if (bodyBuf != null) { + bodyBuf.release(); + } + } + + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + + ResponseHead.Builder headBuilder = ResponseHead.newBuilder(); + headBuilder.setFromHost(InetAddress.getLocalHost().getHostAddress()); + + ResponseBody.Builder bodyBuilder = ResponseBody.newBuilder(); + + bodyBuilder.setVersion(VERSION); + bodyBuilder.setId(request.getCorrelationId()); + if (response.getException() != null) { + headBuilder.setCode(BaiduRpcErrno.Errno.EINTERNAL_VALUE); + headBuilder.setText(response.getException().getMessage()); + } else { + headBuilder.setCode(0); + headBuilder.setText(SUCCESS_TEXT); + headBuilder.setCompressType(request.getCompressType()); + + Compress compress = compressManager.getCompress(request.getCompressType()); + ByteBuf responseProtoBuf = compress.compressOutput( + response.getResult(), response.getRpcMethodInfo()); + + bodyBuilder.setSerializedResponse(ByteString.copyFrom(responseProtoBuf.nioBuffer())); + + } + + PublicPbrpcResponse pbres = PublicPbrpcResponse.newBuilder() + .setResponseHead(headBuilder.build()) + .addResponseBody(bodyBuilder.build()) + .build(); + + // nshead + NSHead nsHead = new NSHead(); + nsHead.logId = (int) request.getLogId(); + nsHead.magicNumber = NSHead.NSHEAD_MAGIC_NUM; + nsHead.provider = PROVIDER; + nsHead.version = NSHEAD_VERSION; + nsHead.bodyLength = pbres.getSerializedSize(); + + byte[] nsHeadBytes = nsHead.toBytes(); + return Unpooled.wrappedBuffer(nsHeadBytes, request.getRpcMethodInfo().inputEncode(pbres)); + + } + + @Override + public boolean isCoexistence() { + return false; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/SPHead.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/SPHead.java new file mode 100644 index 00000000..0910fddd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/SPHead.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.push; + +/** + * * server push 网络交互统一的包头,注释包含为(M)的为必须遵循的规范 + */ +public interface SPHead { + + /** + * 业务请求 + */ + int TYPE_REQUEST = 0; + + /** + * 业务返回 + */ + int TYPE_RESPONSE = 1; + + /** + * server push的请求 + */ + int TYPE_PUSH_REQUEST = 2; + + /** + * server push的返回 + */ + int TYPE_PUSH_RESPONSE = 3; + + /** + * register请求 + */ + int TYPE_REGISTER_REQUEST = 4; + + /** + * register返回 + */ + int TYPE_REGISTER_RESPONSE = 5; + + long getLogId(); + + void setLogId(long logId); + + long getCorrelationId(); + + void setCorrelationId(long correlationId); + + int getType(); + + void setType(int type); + + @Override + int hashCode(); + + @Override + boolean equals(Object obj); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushPacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushPacket.java new file mode 100644 index 00000000..31aadb58 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushPacket.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.protocol.push; + +public abstract class ServerPushPacket { + + protected SPHead spHead; // spHead请求头 + + public SPHead getSpHead() { + return spHead; + } + + public void setSpHead(SPHead spHead) { + this.spHead = spHead; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocol.java new file mode 100644 index 00000000..d6b55b19 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocol.java @@ -0,0 +1,20 @@ +package com.baidu.brpc.protocol.push; + +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.Response; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; + +public interface ServerPushProtocol extends Protocol { + + SPHead createSPHead(); + + SPHead headFromByteBuf(ByteBuf buf) throws BadSchemaException; + + ByteBuf headToBytes(SPHead spHead); + + Response decodeServerPushResponse(Object in, ChannelHandlerContext ctx); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocolFactory.java new file mode 100644 index 00000000..70f9425a --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/ServerPushProtocolFactory.java @@ -0,0 +1,23 @@ +package com.baidu.brpc.protocol.push; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; +import com.baidu.brpc.protocol.push.impl.DefaultServerPushProtocol; + +public class ServerPushProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new DefaultServerPushProtocol(encoding); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultSPHead.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultSPHead.java new file mode 100644 index 00000000..092a6515 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultSPHead.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.push.impl; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.baidu.brpc.protocol.push.SPHead; + +/** + * 2+2+8+8+16+4+4+4=48 byte in total. + */ +public class DefaultSPHead implements SPHead { + + public static final int SPHEAD_LENGTH = 48; + public static final int SPHEAD_MAGIC_NUM = 0xfb201906; + public static final int PROVIDER_LENGTH = 16; + + public static final byte[] ZEROS = new byte[PROVIDER_LENGTH]; + + public short id = 0x00; // 2 + + public short version = 0x01; // 2 + + public long logId; // 8 + + public long correlationId; // 8 + + public String provider = ""; // 16 + + public int magicNumber = SPHEAD_MAGIC_NUM; // 4 + + public int type = 0; // 4 + + public int bodyLength = 0; // 4 + + public DefaultSPHead(int logId, int correlationId, short id, short version, String provider, int bodyLength) { + this.logId = logId; + this.correlationId = correlationId; + this.id = id; + this.version = version; + if (provider != null) { + this.provider = provider; + } + this.bodyLength = bodyLength; + } + + public DefaultSPHead(int correlationId, int bodyLength) { + this.correlationId = correlationId; + this.bodyLength = bodyLength; + } + + public DefaultSPHead() { + } + + @Override + public long getLogId() { + return logId; + } + + @Override + public void setLogId(long logId) { + this.logId = logId; + } + + @Override + public long getCorrelationId() { + return correlationId; + } + + @Override + public void setCorrelationId(long correlationId) { + this.correlationId = correlationId; + } + + @Override + public int getType() { + return type; + } + + @Override + public void setType(int type) { + this.type = type; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(id).append(version).append(logId).append(magicNumber).append(type) + .append(bodyLength).toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DefaultSPHead)) { + return false; + } + DefaultSPHead other = (DefaultSPHead) obj; + return new EqualsBuilder().append(id, other.id).append(version, other.version).append(logId, other.logId) + .append(correlationId, other.correlationId) + .append(type, other.type).append(bodyLength, other.bodyLength).isEquals(); + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("id", Integer.toHexString(id)) + .append("version", Integer.toHexString(version)) + .append("logId", Long.toHexString(logId) + "(" + logId + ")") + .append("correlationId", Long.toHexString(correlationId) + "(" + correlationId + ")") + .append("provider", provider) + .append("magicNumber", Integer.toHexString(magicNumber)) + .append("type", Integer.toHexString(type)) + .append("bodyLength", Integer.toHexString(bodyLength)).toString(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushPacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushPacket.java new file mode 100644 index 00000000..8d9ed041 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushPacket.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.push.impl; + +import com.baidu.brpc.protocol.push.ServerPushPacket; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class DefaultServerPushPacket extends ServerPushPacket { + + private ByteBuf bodyBuf; // body + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushProtocol.java new file mode 100644 index 00000000..b02d8564 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/DefaultServerPushProtocol.java @@ -0,0 +1,370 @@ +package com.baidu.brpc.protocol.push.impl; + +import static com.baidu.brpc.protocol.push.impl.DefaultSPHead.PROVIDER_LENGTH; +import static com.baidu.brpc.protocol.push.impl.DefaultSPHead.SPHEAD_LENGTH; +import static com.baidu.brpc.protocol.push.impl.DefaultSPHead.SPHEAD_MAGIC_NUM; + +import org.apache.commons.lang3.Validate; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.server.PushServerRpcFutureManager; +import com.baidu.brpc.server.ServiceManager; +import com.dyuproject.protostuff.LinkedBuffer; +import com.dyuproject.protostuff.ProtobufIOUtil; +import com.dyuproject.protostuff.Schema; +import com.dyuproject.protostuff.runtime.RuntimeSchema; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@SuppressWarnings("unchecked") +public class DefaultServerPushProtocol implements ServerPushProtocol { + protected String encoding = "utf-8"; + + public DefaultServerPushProtocol(String encoding) { + if (encoding != null) { + this.encoding = encoding; + } + } + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + Validate.notEmpty(request.getArgs(), "args must not be empty"); + ByteBuf bodyBuf = encodeRequestBody(request, request.getRpcMethodInfo()); + DefaultSPHead spHead = (DefaultSPHead) request.getSpHead(); + Validate.notNull(bodyBuf); + spHead.bodyLength = bodyBuf.readableBytes(); + spHead.logId = request.getLogId(); + spHead.setCorrelationId(request.getCorrelationId()); + + ByteBuf headerBuf = headToBytes(spHead); + + return Unpooled.wrappedBuffer(headerBuf, bodyBuf); + } + + @Override + public void beforeRequestSent(Request request, RpcClient rpcClient, BrpcChannel channelGroup) { + + } + + /** + * decode 从客户端返回的 serverPushResponse + * + * @param in + * @param ctx + * + * @return + * + * @throws Exception + */ + public Response decodeServerPushResponse(Object in, ChannelHandlerContext ctx) { + DefaultServerPushPacket packet = (DefaultServerPushPacket) in; + RpcResponse rpcResponse = new RpcResponse(); + Long correlationId = packet.getSpHead().getCorrelationId(); + + RpcFuture future = PushServerRpcFutureManager.getInstance().removeRpcFuture(correlationId); + rpcResponse.setCorrelationId(correlationId); + + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + + ByteBuf bodyBuf = packet.getBodyBuf(); + SPBody spBody = decodeBodyByteBuf(bodyBuf); + Object responseBody = spBody.getContent(); + if (responseBody == null) { + return null; + } + + rpcResponse.setResult(responseBody); + return rpcResponse; + } + + @Override + public Response decodeResponse(Object in, ChannelHandlerContext ctx) throws Exception { + DefaultServerPushPacket packet = (DefaultServerPushPacket) in; + RpcResponse rpcResponse = new RpcResponse(); + // channel info是在客户端生成连接池的时候生成的 + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + Long correlationId = packet.getSpHead().getCorrelationId(); + rpcResponse.setCorrelationId(correlationId); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + + if (future == null || future.getRpcMethodInfo() == null) { + // rpc method info为null,表示register请求 + try { + ByteBuf byteBuf = packet.getBodyBuf(); + byteBuf.release(); + } catch (Exception e) { + throw new RpcException(e); + } + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + SPBody spBody = decodeBodyByteBuf(packet.getBodyBuf()); + Object responseBody = spBody.getContent(); + if (responseBody == null) { + return null; + } + + rpcResponse.setResult(responseBody); + return rpcResponse; + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + ByteBuf bodyBuf = encodeResponseBody(response.getResult(), response.getRpcMethodInfo()); + DefaultSPHead spHead = (DefaultSPHead) response.getSpHead(); + if (spHead == null) { + spHead = new DefaultSPHead((int) response.getCorrelationId(), bodyBuf.readableBytes()); + } else { + spHead.bodyLength = bodyBuf.readableBytes(); + } + spHead.correlationId = response.getCorrelationId(); + switch (request.getSpHead().getType()) { + case SPHead.TYPE_PUSH_REQUEST: + spHead.type = SPHead.TYPE_PUSH_RESPONSE; + break; + case SPHead.TYPE_REGISTER_REQUEST: + spHead.type = SPHead.TYPE_REGISTER_RESPONSE; + break; + default: + spHead.type = SPHead.TYPE_RESPONSE; + } + ByteBuf headerBuf = headToBytes(spHead); + + return Unpooled.wrappedBuffer(headerBuf, bodyBuf); + } + + @Override + public void afterResponseSent(Request request, Response response, ChannelFuture channelFuture) { + + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.createRequest(); + DefaultServerPushPacket spPacket = (DefaultServerPushPacket) packet; + ByteBuf bodyBuf = ((DefaultServerPushPacket) packet).getBodyBuf(); + request.setLogId(spPacket.getSpHead().getLogId()); + request.setCorrelationId(spPacket.getSpHead().getCorrelationId()); + request.setSpHead(((DefaultServerPushPacket) packet).getSpHead()); + // IMPORTANT: if register request, it do not need send response. + // and the request param is string. + if (request.getSpHead().getType() == SPHead.TYPE_REGISTER_REQUEST) { + request.setOneWay(true); + } + SPBody spBody = decodeBodyByteBuf(bodyBuf); + decodeRequestBody(spBody, request); + return request; + } + + @Override + public boolean returnChannelBeforeResponse() { + return false; + } + + @Override + public DefaultServerPushPacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, + boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < DefaultSPHead.SPHEAD_LENGTH) { + throw new NotEnoughDataException(); + } + DefaultServerPushPacket packet = new DefaultServerPushPacket(); + ByteBuf fixHeaderBuf = in.retainedSlice(DefaultSPHead.SPHEAD_LENGTH); + try { + + DefaultSPHead spHead = headFromByteBuf(fixHeaderBuf); + packet.setSpHead(spHead); + int bodyLength = spHead.bodyLength; + + // 512M + if (bodyLength > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodyLength); + } + + if (in.readableBytes() < DefaultSPHead.SPHEAD_LENGTH + bodyLength) { + throw new NotEnoughDataException(); + } + + in.skipBytes(DefaultSPHead.SPHEAD_LENGTH); + ByteBuf bodyBuf = in.readRetainedSlice(bodyLength); + packet.setBodyBuf(bodyBuf); + return packet; + } finally { + fixHeaderBuf.release(); + } + } + + public SPBody decodeBodyByteBuf(ByteBuf bodyByteBuf) { + try { + int readableBytes = bodyByteBuf.readableBytes(); + byte[] bodyBytes = new byte[readableBytes]; + bodyByteBuf.readBytes(bodyBytes); + Schema schema = RuntimeSchema.getSchema(SPBody.class); + SPBody spBody = new SPBody(); + ProtobufIOUtil.mergeFrom(bodyBytes, spBody, schema); + return spBody; + } catch (Exception e) { + throw new RpcException(e); + } finally { + if (bodyByteBuf != null) { + bodyByteBuf.release(); + } + } + } + + @Override + public Request createRequest() { + // tcp protocol implementation, http protocols should override this method + return new RpcRequest(); + } + + @Override + public Response createResponse() { + // tcp protocol implementation, http protocols should override this method + return new RpcResponse(); + } + + @Override + public Request getRequest() { + // tcp protocol implementation, http protocols should override this method + Request request = RpcRequest.getRpcRequest(); + request.reset(); + return request; + } + + @Override + public Response getResponse() { + // tcp protocol implementation, http protocols should override this method + Response response = RpcResponse.getRpcResponse(); + response.reset(); + return response; + } + + @Override + public boolean isCoexistence() { + return true; + } + + public ByteBuf encodeRequestBody(Request request, RpcMethodInfo rpcMethodInfo) { + Validate.notNull(request, "body must not be empty"); + + SPBody spBody = new SPBody(); + spBody.setServiceName(request.getServiceName()); + spBody.setMethodName(request.getMethodName()); + // IMPORTANT: if it is register request, the argument is String. + // So the push protocol should deal with it specially. + spBody.setParameters(request.getArgs()); + byte[] bytes; + + Schema schema = RuntimeSchema.getSchema(SPBody.class); + bytes = ProtobufIOUtil.toByteArray(spBody, schema, LinkedBuffer.allocate(500)); + + return Unpooled.wrappedBuffer(bytes); + + } + + public ByteBuf encodeResponseBody(Object result, RpcMethodInfo rpcMethodInfo) { + Validate.notNull(result, "body must not be empty"); + + SPBody spBody = new SPBody(); + spBody.setServiceName(rpcMethodInfo.getServiceName()); + spBody.setMethodName(rpcMethodInfo.getMethodName()); + spBody.setContent(result); + byte[] bytes; + Schema schema = RuntimeSchema.getSchema(SPBody.class); + bytes = ProtobufIOUtil.toByteArray(spBody, schema, LinkedBuffer.allocate(500)); + return Unpooled.wrappedBuffer(bytes); + } + + public void decodeRequestBody(SPBody body, Request request) { + String serviceName = body.getServiceName(); + String methodName = body.getMethodName(); + RpcMethodInfo rpcMethodInfo = ServiceManager.getInstance().getService(serviceName, methodName); + Validate.notNull(rpcMethodInfo, + "find no method provider for service:" + serviceName + " , method:" + methodName); + request.setArgs(body.getParameters()); + request.setServiceName(body.getServiceName()); + request.setMethodName(methodName); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTarget(rpcMethodInfo.getTarget()); + request.setTargetMethod(rpcMethodInfo.getMethod()); + } + + // sp head + @Override + public SPHead createSPHead() { + return new DefaultSPHead(); + } + + @Override + public DefaultSPHead headFromByteBuf(ByteBuf buf) throws BadSchemaException { + DefaultSPHead head = new DefaultSPHead(); + if (buf.readableBytes() < SPHEAD_LENGTH) { + throw new IllegalArgumentException("not enough bytes to read"); + } + head.id = buf.readShortLE(); + head.version = buf.readShortLE(); + head.logId = buf.readLongLE(); + head.correlationId = buf.readLongLE(); + byte[] bytes = new byte[PROVIDER_LENGTH]; + buf.readBytes(bytes); + int n = 0; + while (n < bytes.length && bytes[n] != 0) { + n++; + } + head.provider = new String(bytes, 0, n); + head.magicNumber = buf.readIntLE(); + if (head.magicNumber != SPHEAD_MAGIC_NUM) { + throw new BadSchemaException("nshead magic number does not match"); + } + head.type = buf.readIntLE(); + head.bodyLength = buf.readIntLE(); + return head; + } + + @Override + public ByteBuf headToBytes(SPHead spHead) { + DefaultSPHead usedSpHead = (DefaultSPHead) spHead; + ByteBuf buffer = Unpooled.buffer(SPHEAD_LENGTH); + buffer.writeShortLE(usedSpHead.id); + buffer.writeShortLE(usedSpHead.version); + buffer.writeLongLE(usedSpHead.logId); + buffer.writeLongLE(usedSpHead.correlationId); + byte[] providerBytes = usedSpHead.provider.getBytes(); + + if (providerBytes.length >= PROVIDER_LENGTH) { + buffer.writeBytes(providerBytes, 0, PROVIDER_LENGTH); + } else { + buffer.writeBytes(providerBytes, 0, providerBytes.length); + buffer.writeBytes(DefaultSPHead.ZEROS, 0, PROVIDER_LENGTH - providerBytes.length); + } + buffer.writeIntLE(usedSpHead.magicNumber); + buffer.writeIntLE(usedSpHead.type); + buffer.writeIntLE(usedSpHead.bodyLength); + return buffer; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/SPBody.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/SPBody.java new file mode 100644 index 00000000..8593a231 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/push/impl/SPBody.java @@ -0,0 +1,68 @@ +package com.baidu.brpc.protocol.push.impl; + +import java.util.Map; + +public class SPBody { + + private String serviceName; + + private String methodName; + + private Object[] parameters; + + private Object content; + + private Class[] parameterTypes; + + private Map attachments; + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public Object[] getParameters() { + return parameters; + } + + public void setParameters(Object[] parameters) { + this.parameters = parameters; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public void setParameterTypes(Class[] parameterTypes) { + this.parameterTypes = parameterTypes; + } + + public Map getAttachments() { + return attachments; + } + + public void setAttachments(Map attachments) { + this.attachments = attachments; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Object getContent() { + return content; + } + + public void setContent(Object content) { + this.content = content; + } + + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcDecodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcDecodePacket.java new file mode 100644 index 00000000..63f233aa --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcDecodePacket.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.sofa; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Setter +@Getter +public class SofaRpcDecodePacket { + private ByteBuf metaBuf; + private ByteBuf protoBuf; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcEncodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcEncodePacket.java new file mode 100644 index 00000000..662bddbd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcEncodePacket.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.sofa; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Setter +@Getter +public class SofaRpcEncodePacket { + private SofaRpcProto.SofaRpcMeta rpcMeta; + private ByteBuf proto; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocol.java new file mode 100644 index 00000000..80870f18 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocol.java @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.sofa; + +import java.util.Arrays; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.compress.Compress; +import com.baidu.brpc.compress.CompressManager; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.BaiduRpcErrno; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ProtobufUtils; +import com.baidu.brpc.utils.RpcMetaUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; + +/** + * Notes on SOFA PBRPC Protocol: + *

    + *
  • Header format is ["SOFA"][meta_size] + * [body_size(64)][message_size(64)], + * 24 bytes in total + *
  • + *
  • {@code body_size} and {@code meta_size} are NOT in + * network byte order (little endian) + *
  • + *
  • meta of request and response are same, distinguished by SofaRpcMeta#type
  • + *
  • sofa-pbrpc does not conduct log_id.
  • + *
  • sofa-pbrpc does not support attachment.
  • + *
+ */ +public class SofaRpcProtocol extends AbstractProtocol { + + private static final Logger LOG = LoggerFactory.getLogger(SofaRpcProtocol.class); + private final static byte[] MAGIC_HEAD = "SOFA".getBytes(); + private static final int FIXED_LEN = 24; + private static final SofaRpcProto.SofaRpcMeta defaultRpcMetaInstance = + SofaRpcProto.SofaRpcMeta.getDefaultInstance(); + private static final CompressManager compressManager = CompressManager.getInstance(); + + @Override + public SofaRpcDecodePacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < FIXED_LEN) { + throw notEnoughDataException; + } + ByteBuf fixHeaderBuf = in.retainedSlice(FIXED_LEN); + try { + byte[] magic = new byte[4]; + fixHeaderBuf.readBytes(magic); + if (!Arrays.equals(magic, MAGIC_HEAD)) { + throw new BadSchemaException("not valid magic head for sofa"); + } + int metaSize = fixHeaderBuf.readIntLE(); + int bodySize = (int) fixHeaderBuf.readLongLE(); + int msgSize = (int) fixHeaderBuf.readLongLE(); + + if (msgSize != metaSize + bodySize) { + throw new BadSchemaException("msgSize != metaSize + bodySize"); + } + if (in.readableBytes() < FIXED_LEN + msgSize) { + throw notEnoughDataException; + } + + // 512M + if (bodySize > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodySize); + } + + in.skipBytes(FIXED_LEN); + SofaRpcDecodePacket packet = new SofaRpcDecodePacket(); + try { + // meta + ByteBuf metaBuf = in.readRetainedSlice(metaSize); + packet.setMetaBuf(metaBuf); + + // body + ByteBuf protoBuf = in.readRetainedSlice(bodySize); + packet.setProtoBuf(protoBuf); + return packet; + } catch (Exception ex) { + LOG.debug("decode failed, ex={}", ex.getMessage()); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex); + } + } finally { + fixHeaderBuf.release(); + } + } + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + SofaRpcEncodePacket requestPacket = new SofaRpcEncodePacket(); + SofaRpcProto.SofaRpcMeta.Builder metaBuilder = SofaRpcProto.SofaRpcMeta.newBuilder(); + metaBuilder.setType(SofaRpcProto.SofaRpcMeta.Type.REQUEST); + metaBuilder.setSequenceId(request.getCorrelationId()); + int compressType = request.getCompressType(); + metaBuilder.setCompressType(getSofaCompressType(compressType)); + + RpcMetaUtils.RpcMetaInfo rpcMetaInfo = RpcMetaUtils.parseRpcMeta(request.getTargetMethod()); + metaBuilder.setMethod(rpcMetaInfo.getServiceName() + "." + rpcMetaInfo.getMethodName()); + requestPacket.setRpcMeta(metaBuilder.build()); + + Object proto = request.getArgs()[0]; + Compress compress = compressManager.getCompress(compressType); + ByteBuf protoBuf = compress.compressInput(proto, request.getRpcMethodInfo()); + requestPacket.setProto(protoBuf); + + return encode(requestPacket); + } + + @Override + public RpcResponse decodeResponse(Object packet, ChannelHandlerContext ctx) throws Exception { + SofaRpcDecodePacket responsePacket = (SofaRpcDecodePacket) packet; + ByteBuf metaBuf = responsePacket.getMetaBuf(); + ByteBuf protoBuf = responsePacket.getProtoBuf(); + try { + RpcResponse rpcResponse = new RpcResponse(); + SofaRpcProto.SofaRpcMeta responseMeta = (SofaRpcProto.SofaRpcMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcMetaInstance); + Long correlationId = responseMeta.getSequenceId(); + rpcResponse.setCorrelationId(correlationId); + + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + int compressType = getStandardCompressType(responseMeta.getCompressType()); + rpcResponse.setCompressType(compressType); + + try { + if (responseMeta != null && responseMeta.getErrorCode() == 0) { + Compress compress = compressManager.getCompress(compressType); + Object result = compress.uncompressOutput( + protoBuf, future.getRpcMethodInfo()); + rpcResponse.setResult(result); + } else { + rpcResponse.setException(new RpcException( + RpcException.SERVICE_EXCEPTION, responseMeta.getReason())); + } + } catch (Exception ex) { + LOG.warn("decode response failed"); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "decode response failed", ex); + } + return rpcResponse; + } finally { + if (metaBuf != null) { + metaBuf.release(); + } + if (protoBuf != null) { + protoBuf.release(); + } + } + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.createRequest(); + SofaRpcDecodePacket requestPacket = (SofaRpcDecodePacket) packet; + ByteBuf metaBuf = requestPacket.getMetaBuf(); + ByteBuf protoBuf = requestPacket.getProtoBuf(); + try { + SofaRpcProto.SofaRpcMeta requestMeta = (SofaRpcProto.SofaRpcMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcMetaInstance); + request.setCorrelationId(requestMeta.getSequenceId()); + if (StringUtils.isBlank(requestMeta.getMethod())) { + String errorMsg = "method is null"; + LOG.error(errorMsg); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + return request; + } + ServiceManager serviceManager = ServiceManager.getInstance(); + RpcMethodInfo rpcMethodInfo = serviceManager.getService(requestMeta.getMethod().toLowerCase()); + if (rpcMethodInfo == null) { + String errorMsg = String.format("Fail to find method=%s", requestMeta.getMethod()); + LOG.error(errorMsg); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + return request; + } + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setTarget(rpcMethodInfo.getTarget()); + + int compressType = getStandardCompressType(requestMeta.getCompressType()); + request.setCompressType(compressType); + Compress compress = compressManager.getCompress(compressType); + try { + Object requestProto = compress.uncompressInput( + protoBuf, rpcMethodInfo); + request.setArgs(new Object[] {requestProto}); + } catch (Exception ex) { + String errorMsg = String.format("decode request failed, msg=%s", ex.getMessage()); + LOG.error(errorMsg); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, errorMsg); + } + return request; + } finally { + if (metaBuf != null) { + metaBuf.release(); + } + if (protoBuf != null) { + protoBuf.release(); + } + } + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + SofaRpcEncodePacket responsePacket = new SofaRpcEncodePacket(); + SofaRpcProto.SofaRpcMeta.Builder metaBuilder = SofaRpcProto.SofaRpcMeta.newBuilder(); + metaBuilder.setType(SofaRpcProto.SofaRpcMeta.Type.RESPONSE); + metaBuilder.setSequenceId(response.getCorrelationId()); + int compressType = response.getCompressType(); + metaBuilder.setCompressType(getSofaCompressType(compressType)); + + if (response.getException() != null) { + metaBuilder.setErrorCode(BaiduRpcErrno.Errno.ERESPONSE_VALUE); + metaBuilder.setReason(response.getException().getMessage()); + responsePacket.setRpcMeta(metaBuilder.build()); + } else { + Object responseBodyMessage = response.getResult(); + Compress compress = compressManager.getCompress(compressType); + ByteBuf responseProtoBuf = compress.compressOutput(responseBodyMessage, response.getRpcMethodInfo()); + responsePacket.setProto(responseProtoBuf); + metaBuilder.setErrorCode(0); + responsePacket.setRpcMeta(metaBuilder.build()); + } + return encode(responsePacket); + } + + @Override + public boolean isCoexistence() { + return true; + } + + protected ByteBuf encode(SofaRpcEncodePacket packet) throws Exception { + // meta buf + byte[] metaBytes = packet.getRpcMeta().toByteArray(); + ByteBuf metaBuf = Unpooled.wrappedBuffer(metaBytes); + int metaSize = metaBytes.length; + + // header buf + ByteBuf headerBuf = Unpooled.buffer(FIXED_LEN); + headerBuf.writeBytes(MAGIC_HEAD); + headerBuf.writeIntLE(metaSize); + ByteBuf protoBuf = packet.getProto(); + if (protoBuf != null) { + int protoSize = protoBuf.readableBytes(); + headerBuf.writeLongLE(protoSize); + headerBuf.writeLongLE(metaSize + protoSize); + return Unpooled.wrappedBuffer(headerBuf, metaBuf, protoBuf); + } else { + headerBuf.writeLongLE(0); + headerBuf.writeLongLE(metaSize); + return Unpooled.wrappedBuffer(headerBuf, metaBuf); + } + } + + protected SofaRpcProto.SofaCompressType getSofaCompressType(int compressType) { + SofaRpcProto.SofaCompressType sofaCompressType; + switch (compressType) { + case Options.CompressType.COMPRESS_TYPE_NONE_VALUE: + sofaCompressType = SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_NONE; + break; + case Options.CompressType.COMPRESS_TYPE_SNAPPY_VALUE: + sofaCompressType = SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_SNAPPY; + break; + case Options.CompressType.COMPRESS_TYPE_GZIP_VALUE: + sofaCompressType = SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_GZIP; + break; + case Options.CompressType.COMPRESS_TYPE_ZLIB_VALUE: + sofaCompressType = SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_ZLIB; + break; + case Options.CompressType.COMPRESS_TYPE_LZ4_VALUE: + sofaCompressType = SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_LZ4; + break; + default: + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "not support compress type"); + } + return sofaCompressType; + } + + protected int getStandardCompressType(SofaRpcProto.SofaCompressType sofaCompressType) { + int standardCompressType; + switch (sofaCompressType.getNumber()) { + case SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_NONE_VALUE: + standardCompressType = Options.CompressType.COMPRESS_TYPE_NONE_VALUE; + break; + case SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_SNAPPY_VALUE: + standardCompressType = Options.CompressType.COMPRESS_TYPE_SNAPPY_VALUE; + break; + case SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_GZIP_VALUE: + standardCompressType = Options.CompressType.COMPRESS_TYPE_GZIP_VALUE; + break; + case SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_ZLIB_VALUE: + standardCompressType = Options.CompressType.COMPRESS_TYPE_ZLIB_VALUE; + break; + case SofaRpcProto.SofaCompressType.SOFA_COMPRESS_TYPE_LZ4_VALUE: + standardCompressType = Options.CompressType.COMPRESS_TYPE_LZ4_VALUE; + break; + default: + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "not support compress type"); + } + return standardCompressType; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocolFactory.java new file mode 100644 index 00000000..561161f5 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/sofa/SofaRpcProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.sofa; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class SofaRpcProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_SOFA_PBRPC_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new SofaRpcProtocol(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcDecodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcDecodePacket.java new file mode 100644 index 00000000..016ab056 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcDecodePacket.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Setter +@Getter +public class BaiduRpcDecodePacket { + private ByteBuf metaBuf; + private ByteBuf protoAndAttachmentBuf; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcEncodePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcEncodePacket.java new file mode 100644 index 00000000..d09d2533 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcEncodePacket.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.Setter; + +/** + * Created by huwenwei on 2017/9/23. + */ +@Setter +@Getter +public class BaiduRpcEncodePacket { + private BaiduRpcProto.RpcMeta rpcMeta; + private ByteBuf proto; + private ByteBuf attachment; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocol.java new file mode 100644 index 00000000..ec003718 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocol.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.compress.Compress; +import com.baidu.brpc.compress.CompressManager; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.BaiduRpcErrno; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ProtobufUtils; +import com.google.protobuf.ByteString; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; + +/** + * Notes on Baidu RPC Protocol: + *
    + *
  • Header format is ["PRPC"][body_size][meta_size + * ], 12 bytes in total + *
  • + *
  • {@code body_size} and {@code meta_size} are in network byte + * order (big endian) + *
  • + *
  • Use service->full_name() and method_name to identify the service and + * method to call
  • + *
  • {@code attachment_size} is set iff request/response has attachment
  • + *
  • The following fields of rpc are not supported yet: + *
      + *
    • chunk_info
    • + *
    + *
  • + *
+ * Created by huwenwei on 2017/9/22. + */ +public class BaiduRpcProtocol extends AbstractProtocol { + + private static final Logger LOG = LoggerFactory.getLogger(BaiduRpcProtocol.class); + private static final byte[] MAGIC_HEAD = "PRPC".getBytes(); + private static final int FIXED_LEN = 12; + private static final BaiduRpcProto.RpcMeta defaultRpcMetaInstance = BaiduRpcProto.RpcMeta.getDefaultInstance(); + private static final CompressManager compressManager = CompressManager.getInstance(); + private static final ServiceManager serviceManager = ServiceManager.getInstance(); + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + BaiduRpcEncodePacket packet = new BaiduRpcEncodePacket(); + BaiduRpcProto.RpcMeta.Builder metaBuilder = BaiduRpcProto.RpcMeta.newBuilder(); + metaBuilder.setCorrelationId(request.getCorrelationId()); + int compressType = request.getCompressType(); + metaBuilder.setCompressType(request.getCompressType()); + + BaiduRpcProto.RpcRequestMeta.Builder requestMeta = BaiduRpcProto.RpcRequestMeta.newBuilder(); + requestMeta.setLogId(request.getLogId()); + requestMeta.setServiceName(request.getServiceName()); + requestMeta.setMethodName(request.getMethodName()); + if (request.getTraceId() != null) { + requestMeta.setTraceId(request.getTraceId()); + } + if (request.getSpanId() != null) { + requestMeta.setSpanId(request.getSpanId()); + } + if (request.getParentSpanId() != null) { + requestMeta.setSpanId(request.getParentSpanId()); + } + if (request.getKvAttachment() != null) { + for (Map.Entry kv : request.getKvAttachment().entrySet()) { + requestMeta.addExtFieldsBuilder().setKey(kv.getKey()).setValue((String) kv.getValue()); + } + } + metaBuilder.setRequest(requestMeta.build()); + + // proto + Compress compress = compressManager.getCompress(compressType); + ByteBuf protoBuf = compress.compressInput(request.getArgs()[0], request.getRpcMethodInfo()); + packet.setProto(protoBuf); + + // attachment + if (request.getBinaryAttachment() != null + && request.getBinaryAttachment().isReadable()) { + packet.setAttachment(request.getBinaryAttachment()); + metaBuilder.setAttachmentSize(request.getBinaryAttachment().readableBytes()); + } + // auth + if (request.getAuth() != null) { + metaBuilder.setAuthenticationData(ByteString.copyFrom(request.getAuth().getBytes())); + } + packet.setRpcMeta(metaBuilder.build()); + + return encode(packet); + } + + public RpcResponse decodeResponse(Object packet, ChannelHandlerContext ctx) throws Exception { + BaiduRpcDecodePacket responsePacket = (BaiduRpcDecodePacket) packet; + ByteBuf metaBuf = responsePacket.getMetaBuf(); + ByteBuf protoAndAttachmentBuf = responsePacket.getProtoAndAttachmentBuf(); + try { + BaiduRpcProto.RpcMeta rpcMeta = (BaiduRpcProto.RpcMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcMetaInstance); + RpcResponse rpcResponse = new RpcResponse(); + long correlationId = rpcMeta.getCorrelationId(); + rpcResponse.setCorrelationId(correlationId); + + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + RpcFuture future = channelInfo.removeRpcFuture(rpcResponse.getCorrelationId()); + if (future == null) { + return rpcResponse; + } + rpcResponse.setRpcFuture(future); + BaiduRpcProto.RpcResponseMeta responseMeta = rpcMeta.getResponse(); + try { + if (responseMeta != null && responseMeta.getErrorCode() == 0) { + Compress compress = compressManager.getCompress(rpcMeta.getCompressType()); + int protoSize = protoAndAttachmentBuf.readableBytes() + - rpcMeta.getAttachmentSize(); + // proto body + ByteBuf protoBuf = protoAndAttachmentBuf.readSlice(protoSize); + Object proto = compress.uncompressOutput(protoBuf, future.getRpcMethodInfo()); + rpcResponse.setResult(proto); + + // attachment + if (rpcMeta.getAttachmentSize() > 0) { + rpcResponse.setBinaryAttachment(protoAndAttachmentBuf); + protoAndAttachmentBuf = null; + } + } else { + rpcResponse.setException(new RpcException( + RpcException.SERVICE_EXCEPTION, responseMeta.getErrorText())); + } + } catch (Exception ex) { + // 解析失败直接抛异常 + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "decode response failed", ex); + } + return rpcResponse; + } finally { + if (metaBuf != null) { + metaBuf.release(); + } + if (protoAndAttachmentBuf != null) { + protoAndAttachmentBuf.release(); + } + } + } + + @Override + public BaiduRpcDecodePacket decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException { + if (in.readableBytes() < FIXED_LEN) { + throw notEnoughDataException; + } + ByteBuf fixHeaderBuf = in.retainedSlice(FIXED_LEN); + try { + byte[] magic = new byte[4]; + fixHeaderBuf.readBytes(magic); + if (!Arrays.equals(magic, MAGIC_HEAD)) { + throw new BadSchemaException("not valid magic head for brpc"); + } + + int bodySize = fixHeaderBuf.readInt(); + if (in.readableBytes() < FIXED_LEN + bodySize) { + throw notEnoughDataException; + } + // 512M + if (bodySize > 512 * 1024 * 1024) { + throw new TooBigDataException("to big body size:" + bodySize); + } + + int metaSize = fixHeaderBuf.readInt(); + in.skipBytes(FIXED_LEN); + BaiduRpcDecodePacket packet = new BaiduRpcDecodePacket(); + try { + // meta + ByteBuf metaBuf = in.readRetainedSlice(metaSize); + packet.setMetaBuf(metaBuf); + + // proto and attachment + ByteBuf protoAndAttachmentBuf = in.readRetainedSlice(bodySize - metaSize); + packet.setProtoAndAttachmentBuf(protoAndAttachmentBuf); + + return packet; + } catch (Exception ex) { + LOG.warn("decode failed:", ex); + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex); + } + } finally { + fixHeaderBuf.release(); + } + } + + @Override + public Request decodeRequest(Object packet) throws Exception { + Request request = this.createRequest(); + BaiduRpcDecodePacket requestPacket = (BaiduRpcDecodePacket) packet; + ByteBuf metaBuf = requestPacket.getMetaBuf(); + ByteBuf protoAndAttachmentBuf = requestPacket.getProtoAndAttachmentBuf(); + BaiduRpcProto.RpcMeta rpcMeta; + try { + rpcMeta = (BaiduRpcProto.RpcMeta) ProtobufUtils.parseFrom( + metaBuf, defaultRpcMetaInstance); + BaiduRpcProto.RpcRequestMeta requestMeta = rpcMeta.getRequest(); + request.setCorrelationId(rpcMeta.getCorrelationId()); + int compressType = rpcMeta.getCompressType(); + request.setCompressType(compressType); + request.setLogId(requestMeta.getLogId()); + + RpcMethodInfo rpcMethodInfo = serviceManager.getService( + requestMeta.getServiceName(), requestMeta.getMethodName()); + if (rpcMethodInfo == null) { + String errorMsg = String.format("Fail to find service=%s, method=%s", + requestMeta.getServiceName(), requestMeta.getMethodName()); + LOG.error(errorMsg); + request.setException(new RpcException(RpcException.SERVICE_EXCEPTION, errorMsg)); + return request; + } + if (requestMeta.hasTraceId()) { + request.setTraceId(requestMeta.getTraceId()); + } + if (requestMeta.hasSpanId()) { + request.setSpanId(request.getSpanId()); + } + if (requestMeta.hasParentSpanId()) { + request.setParentSpanId(requestMeta.getParentSpanId()); + } + if (requestMeta.getExtFieldsCount() > 0) { + if (request.getKvAttachment() == null) { + request.setKvAttachment(new HashMap()); + } + for (BaiduRpcProto.RpcRequestMetaExtField extField : requestMeta.getExtFieldsList()) { + request.getKvAttachment().put(extField.getKey(), extField.getValue()); + } + } + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setTarget(rpcMethodInfo.getTarget()); + + // auth + if (rpcMeta.getAuthenticationData() != null) { + request.setAuth(new String(rpcMeta.getAuthenticationData().toByteArray())); + } + + // proto body + Compress compress = compressManager.getCompress(compressType); + if (rpcMeta.hasAttachmentSize() && rpcMeta.getAttachmentSize() > 0) { + int protoSize = protoAndAttachmentBuf.readableBytes() - rpcMeta.getAttachmentSize(); + ByteBuf protoBuf = protoAndAttachmentBuf.readSlice(protoSize); + Object proto = compress.uncompressInput(protoBuf, rpcMethodInfo); + request.setArgs(new Object[] {proto}); + request.setBinaryAttachment(protoAndAttachmentBuf); + protoAndAttachmentBuf = null; + } else { + Object proto = compress.uncompressInput(protoAndAttachmentBuf, rpcMethodInfo); + request.setArgs(new Object[] {proto}); + } + return request; + } finally { + if (metaBuf != null) { + metaBuf.release(); + } + if (protoAndAttachmentBuf != null) { + protoAndAttachmentBuf.release(); + } + } + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + BaiduRpcEncodePacket responsePacket = new BaiduRpcEncodePacket(); + BaiduRpcProto.RpcMeta.Builder metaBuilder = BaiduRpcProto.RpcMeta.newBuilder(); + metaBuilder.setCorrelationId(response.getCorrelationId()); + int compressType = response.getCompressType(); + metaBuilder.setCompressType(compressType); + BaiduRpcProto.RpcResponseMeta.Builder responseMetaBuilder = BaiduRpcProto.RpcResponseMeta.newBuilder(); + + if (response.getException() != null) { + responseMetaBuilder.setErrorCode(BaiduRpcErrno.Errno.EINTERNAL_VALUE); + if (StringUtils.isNotBlank(response.getException().getMessage())) { + responseMetaBuilder.setErrorText(response.getException().getMessage()); + } + metaBuilder.setResponse(responseMetaBuilder.build()); + responsePacket.setRpcMeta(metaBuilder.build()); + } else { + responseMetaBuilder.setErrorCode(0); + metaBuilder.setResponse(responseMetaBuilder.build()); + + Object responseProto = response.getResult(); + Compress compress = compressManager.getCompress(compressType); + ByteBuf protoBuf = compress.compressOutput(responseProto, response.getRpcMethodInfo()); + responsePacket.setProto(protoBuf); + + // attachment + if (response.getBinaryAttachment() != null) { + responsePacket.setAttachment(response.getBinaryAttachment()); + metaBuilder.setAttachmentSize(response.getBinaryAttachment().readableBytes()); + } + responsePacket.setRpcMeta(metaBuilder.build()); + } + + return encode(responsePacket); + } + + protected ByteBuf encode(BaiduRpcEncodePacket packet) throws Exception { + byte[] metaBytes = packet.getRpcMeta().toByteArray(); + ByteBuf metaBuf = Unpooled.wrappedBuffer(metaBytes); + int metaSize = metaBytes.length; + + // fixed header buf + ByteBuf headerBuf = Unpooled.buffer(FIXED_LEN); + headerBuf.writeBytes(MAGIC_HEAD); + int bodySize = metaSize; + ByteBuf protoBuf = packet.getProto(); + if (protoBuf != null) { + bodySize += protoBuf.readableBytes(); + } + ByteBuf attachmentBuf = packet.getAttachment(); + if (attachmentBuf != null) { + bodySize += attachmentBuf.readableBytes(); + } + headerBuf.writeInt(bodySize); + headerBuf.writeInt(metaSize); + if (protoBuf != null && attachmentBuf != null) { + return Unpooled.wrappedBuffer(headerBuf, metaBuf, protoBuf, attachmentBuf); + } else if (protoBuf != null) { + return Unpooled.wrappedBuffer(headerBuf, metaBuf, protoBuf); + } else { + return Unpooled.wrappedBuffer(headerBuf, metaBuf); + } + } + + @Override + public boolean isCoexistence() { + return true; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolFactory.java new file mode 100644 index 00000000..67cbcd06 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.standard; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class BaiduRpcProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY - 2; + } + + @Override + public Protocol createProtocol(String encoding) { + return new BaiduRpcProtocol(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateConstants.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateConstants.java new file mode 100644 index 00000000..9e3aa881 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateConstants.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.stargate; + +import java.util.regex.Pattern; + +/** + * copy from Stargate 1.2.18 + */ +public interface StargateConstants { + + /** + * version + */ + String STARGATE_VERSION = "1.2.18"; + + /** + * 全局采用逗号分隔 + */ + Pattern COMMA_SPLIT_PATTERN = Pattern.compile("\\s*[,]+\\s*"); + + /** + * URI里指定默认值,比如有key,那么DEFAULT_KEY_PREFIX+key指定的值就是该key的默认值 + */ + String DEFAULT_KEY_PREFIX = "default."; + + /** + * 服务分组key + */ + String GROUP_KEY = "group"; + + /** + * 服务接口key + */ + String INTERFACE_KEY = "interface"; + + /** + * 服务版本key + */ + String VERSION_KEY = "version"; + + /** + * 服务简单key + */ + String INTERFACE_SIMPLE_KEY = "interface.simple"; + + /** + * zk 上 consumer 目录 + */ + String ZK_CONSUMER_DIR = "consumer"; + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocol.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocol.java new file mode 100644 index 00000000..f58e4e90 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocol.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.stargate; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.AbstractProtocol; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.NetUtils; +import com.dyuproject.protostuff.LinkedBuffer; +import com.dyuproject.protostuff.ProtobufIOUtil; +import com.dyuproject.protostuff.Schema; +import com.dyuproject.protostuff.runtime.RuntimeSchema; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; + +/** + * Stargate Byte format + * head = body体长度,使用一个4位byte表示 + * +--------------------------------------+----------------+ + * + 00000000 00000000 00000000 00000111 | 14 bytes | + * + byte[3] byte[2] byte[1] byte[0] | "HELLO, WORLD" | + * +-----------------------------------+----------------+ + */ +@Slf4j +public class StargateRpcProtocol extends AbstractProtocol { + + private static final int FIXED_HEAD_LEN = 4; + + private static final NotEnoughDataException notEnoughDataException + = new NotEnoughDataException("Stargate not enough data"); + + private static final String SERIALIZATION_EXCEPTION = "decode error,this problem is usually caused by" + + "\n 1: difference of api.jar between server and client." + + "\n 2: server do not catch Exception." + + "\n 3: API contains a type that Stargate does not support. eg:HashMap.keySet()"; + + private static Set redundantAttachments = new HashSet() { + { + add("parameterTypes"); + add("localPort"); + add("remoteHost"); + add("parmeters"); + add("remotePort"); + add("methodName"); + add("consumer.start"); + add("uri"); + add("c.e.i.id"); + add("stargate.sid"); + add("stargate.rid"); + add("localHost"); + add("c.app.name"); + } + }; + + private ServiceManager serviceManager = ServiceManager.getInstance(); + private boolean init = false; + + public void initEnv() { + // init Stargate protoStuff + // docs http://javadox.com/io.protostuff/protostuff-runtime/1.3.8/io/protostuff/runtime/RuntimeEnv.html + if (!init) { + synchronized (StargateRpcProtocol.class) { + if (!init) { + System.setProperty("protostuff.runtime.collection_schema_on_repeated_fields", "true"); + System.setProperty("protostuff.runtime.morph_collection_interfaces", "true"); + System.setProperty("protostuff.runtime.morph_map_interfaces", "true"); + init = true; + } + } + } + } + + @Override + public Object decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws TooBigDataException, NotEnoughDataException, BadSchemaException { + if (in.readableBytes() < FIXED_HEAD_LEN) { + throw notEnoughDataException; + } + ByteBuf head = in.retainedSlice(FIXED_HEAD_LEN); + try { + int bodySize = head.readInt(); + if (in.readableBytes() < bodySize + FIXED_HEAD_LEN) { + throw notEnoughDataException; + } + + // 512M + if (bodySize > 512 * 1024 * 1024) { + throw new TooBigDataException("StarGate too big body size:" + bodySize); + } + + byte[] body = new byte[bodySize]; + in.skipBytes(FIXED_HEAD_LEN); + in.readBytes(body); + return body; + } finally { + head.release(); + } + } + + @Override + public ByteBuf encodeRequest(Request request) throws Exception { + StargateURI stargateURI = new StargateURI + .Builder("star", NetUtils.getLogHost(), 0) + .param("version", request.getSubscribeInfo().getVersion()) + .param("group", request.getSubscribeInfo().getGroup()) + .param("interface", request.getSubscribeInfo().getInterfaceName()) + .param("consumer.id", UUID.randomUUID().toString()) + .build(); + + Method method = request.getTargetMethod(); + StargateRpcRequestPacket requestPacket = new StargateRpcRequestPacket( + stargateURI, + method.getName(), + method.getParameterTypes(), + request.getArgs()); + requestPacket.setId(request.getCorrelationId() + ""); + + if (request.getKvAttachment() != null && !request.getKvAttachment().isEmpty()) { + requestPacket.setAttachments(request.getKvAttachment()); + } + + try { + initEnv(); + Schema schema = RuntimeSchema.getSchema(StargateRpcRequestPacket.class); + byte[] body = ProtobufIOUtil.toByteArray(requestPacket, schema, LinkedBuffer.allocate(500)); + byte[] head = buildHead(body); + return Unpooled.wrappedBuffer(head, body); + } catch (Exception e) { + log.warn(SERIALIZATION_EXCEPTION, e); + throw new BadSchemaException(SERIALIZATION_EXCEPTION, e); + } + } + + /** + * 客户端解码响应操作 + * PS: + * BRPC 有且仅有当BRPC作为客户端时,使用FastFuture的LogId 作为线程绑定ID + */ + @Override + public Response decodeResponse(Object msg, ChannelHandlerContext ctx) throws Exception { + try { + StargateRpcResponsePacket rpcResponse = new StargateRpcResponsePacket(); + Schema schema = RuntimeSchema.getSchema(StargateRpcResponsePacket.class); + ProtobufIOUtil.mergeFrom((byte[]) msg, rpcResponse, schema); + try { + Response response = new RpcResponse(); + response.setResult(rpcResponse.getResult()); + if (rpcResponse.getException() != null) { + if (rpcResponse.getException() instanceof Throwable) { + response.setException((Throwable) rpcResponse.getException()); + } else { + throw new IllegalStateException("stargate response contains an exception which" + + "is not a throwable"); + } + } + long correlationId = Long.parseLong(rpcResponse.getId()); + ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(ctx.channel()); + RpcFuture future = channelInfo.removeRpcFuture(correlationId); + if (future == null) { + return response; + } + response.setRpcFuture(future); + response.setCorrelationId(correlationId); + response.setKvAttachment(rpcResponse.getAttachments()); + return response; + } catch (NumberFormatException n) { + log.error(" when brpc is Client unexpect logId at {}", rpcResponse.getId(), n); + throw new BadSchemaException(SERIALIZATION_EXCEPTION, n); + } + } catch (Exception e) { + log.warn(SERIALIZATION_EXCEPTION, e); + throw new BadSchemaException(SERIALIZATION_EXCEPTION, e); + } + } + + @Override + public Request decodeRequest(Object packet) throws BadSchemaException { + try { + StargateRpcRequestPacket requestPacket = new StargateRpcRequestPacket(); + initEnv(); + Schema schema = RuntimeSchema.getSchema(StargateRpcRequestPacket.class); + ProtobufIOUtil.mergeFrom((byte[]) packet, requestPacket, schema); + + String serviceName = requestPacket.getUri().getServiceName(); + String methodName = requestPacket.getMethodName(); + RpcMethodInfo rpcMethodInfo = serviceManager.getService(serviceName, methodName); + + Request request = new RpcRequest(); + request.setArgs(requestPacket.getParameters()); + request.setServiceName(serviceName); + request.setMethodName(methodName); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTarget(rpcMethodInfo.getTarget()); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setMsg(requestPacket); + if (requestPacket.getAttachments() != null && requestPacket.getAttachments().size() > 0) { + for (Map.Entry entry : requestPacket.getAttachments().entrySet()) { + if (!redundantAttachments.contains(entry.getKey())) { + if (request.getKvAttachment() == null) { + request.setKvAttachment(new HashMap()); + } + request.getKvAttachment().put(entry.getKey(), entry.getValue()); + } + } + } + return request; + } catch (Exception e) { + log.error(" stargate decodeRequest error at {} ", e.getMessage(), e); + throw new BadSchemaException(SERIALIZATION_EXCEPTION, e); + } + } + + @Override + public ByteBuf encodeResponse(Request request, Response response) throws Exception { + try { + StargateRpcRequestPacket stargateRpcRequestPacket = (StargateRpcRequestPacket) request.getMsg(); + StargateRpcResponsePacket responsePacket = new StargateRpcResponsePacket( + stargateRpcRequestPacket.getId(), + response.getResult(), + response.getException()); + + if (response.getKvAttachment() != null && !response.getKvAttachment().isEmpty()) { + responsePacket.setAttachments(response.getKvAttachment()); + } + + Schema schema = RuntimeSchema.getSchema(StargateRpcResponsePacket.class); + byte[] body = ProtobufIOUtil.toByteArray(responsePacket, schema, LinkedBuffer.allocate(500)); + byte[] head = buildHead(body); + + return Unpooled.wrappedBuffer(head, body); + } catch (Exception e) { + log.warn(SERIALIZATION_EXCEPTION, e); + throw new BadSchemaException(SERIALIZATION_EXCEPTION, e); + } + } + + /** + * 根据Body的长度,生产4位数组的Head + * + * @param body 二进制Body + */ + private byte[] buildHead(byte[] body) { + int length = body.length; + return new byte[]{ + (byte) ((length >> 24) & 0xFF), + (byte) ((length >> 16) & 0xFF), + (byte) ((length >> 8) & 0xFF), + (byte) (length & 0xFF) + }; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocolFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocolFactory.java new file mode 100644 index 00000000..d0fda0f2 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcProtocolFactory.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.protocol.stargate; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolFactory; + +public class StargateRpcProtocolFactory implements ProtocolFactory { + + @Override + public Integer getProtocolType() { + return Options.ProtocolType.PROTOCOL_STARGATE_VALUE; + } + + public Integer getPriority() { + return ProtocolFactory.DEFAULT_PRIORITY; + } + + @Override + public Protocol createProtocol(String encoding) { + return new StargateRpcProtocol(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcRequestPacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcRequestPacket.java new file mode 100644 index 00000000..46424558 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcRequestPacket.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.stargate; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.Map; + +/** + * copy from StarGate 1.2.18 + */ +@Setter +@Getter +@ToString +@NoArgsConstructor +public final class StargateRpcRequestPacket { + private String id; + + private String methodName; + + private Object[] parameters; + + private Class[] parameterTypes; + + private Map attachments; + + private StargateURI uri; + + public StargateRpcRequestPacket(StargateURI uri, String methodName, + Class[] parameterTypes, Object[] parameters) { + this.id = StargateUtils.genUUID(); + this.uri = uri; + this.methodName = methodName; + this.parameterTypes = parameterTypes; + this.parameters = parameters; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcResponsePacket.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcResponsePacket.java new file mode 100644 index 00000000..6ff0c442 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateRpcResponsePacket.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.stargate; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.Map; + +/** + * copy from StarGate 1.2.18 + */ +@Setter +@Getter +@ToString +@NoArgsConstructor +public final class StargateRpcResponsePacket { + private String id; + + private Object exception; + + private Object result; + + private Map attachments; + + public StargateRpcResponsePacket(String id, Object result, Throwable exception) { + this.id = id; + this.result = result; + this.exception = exception; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateURI.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateURI.java new file mode 100644 index 00000000..901d37a9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateURI.java @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.stargate; + +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +/** + * copy from Stargate 1.2.18 + */ +public class StargateURI { + + private final String protocol; + + private final String username; + + private final String password; + + private final String host; + + private final int port; + + private final String path; + + private final Map parameters; + + private final Map numbers = new ConcurrentHashMap(); + + // cache + private final transient String ip; + + private final transient String fullString; + + private final transient String identityString; + + private final transient String parameterString; + + private final transient String string; + + public static class Builder { + private final String protocol; + + private final String host; + + private final int port; + + private String username; + + private String password; + + private String path; + + private Map parameters = new HashMap(); + + public Builder(String protocol, String host, int port) { + this.protocol = protocol; + this.host = host; + this.port = port; + } + + public Builder(StargateURI uri) { + this.protocol = uri.getProtocol(); + this.host = uri.getHost(); + this.port = uri.getPort(); + this.username = uri.getUsername(); + this.password = uri.getPassword(); + this.path = uri.getPath(); + this.parameters.putAll(uri.getParameters());// 返回的是UnmodifiableMap + } + + public Builder(String uri) { + this(valueOf(uri)); + } + + public Builder path(String path) { + this.path = path; + return this; + } + + public Builder username(String username) { + this.username = username; + return this; + } + + public Builder password(String password) { + this.password = password; + return this; + } + + public Builder params(String... pairs) { + this.parameters.putAll(StargateUtils.toStringMap(pairs)); + return this; + } + + public Builder params(Map parameters) { + this.parameters.putAll(parameters); + return this; + } + + public Builder paramString(String query) { + if (query == null || query.length() == 0) { + return this; + } + return params(StargateUtils.parseQueryString(query)); + } + + public Builder paramAndEncoded(String key, String value) { + if (value == null || value.length() == 0) { + return this; + } + return param(key, encode(value)); + } + + public Builder param(String key, String value) { + if (key == null || key.length() == 0 || value == null || value.length() == 0) { + return this; + } + this.parameters.put(key, value); + return this; + } + + public Builder param(String key, boolean value) { + return param(key, String.valueOf(value)); + } + + public Builder param(String key, int value) { + return param(key, String.valueOf(value)); + } + + public Builder param(String key, long value) { + return param(key, String.valueOf(value)); + } + + public Builder param(String key, double value) { + return param(key, String.valueOf(value)); + } + + public Builder param(String key, Enum value) { + if (value == null) { + return this; + } + return param(key, String.valueOf(value)); + } + + public Builder param(String key, Number value) { + if (value == null) { + return this; + } + return param(key, String.valueOf(value)); + } + + public Builder paramIfAbsent(String key, String value) { + if (key == null || key.length() == 0 || value == null || value.length() == 0) { + return this; + } + String oldValue = parameters.get(key); + if (oldValue == null) { + oldValue = parameters.get(StargateConstants.DEFAULT_KEY_PREFIX + key); + } + if (oldValue != null && oldValue.length() > 0) { + return this;// has param + } + this.parameters.put(key, value); + return this; + } + + public StargateURI build() { + return new StargateURI(this); + } + } + + public StargateURI(Builder builder) { + this(builder.protocol, builder.username, builder.password, builder.host, builder.port, builder.path, + builder.parameters); + } + + public StargateURI(String protocol, String username, String password, String host, int port, String path, + Map parameters) { + if ((username == null || username.length() == 0) && password != null && password.length() > 0) { + throw new IllegalArgumentException("Invalid uri, password without username!"); + } + this.protocol = protocol; + this.username = username; + this.password = password; + this.host = host; + this.port = (port < 0 ? 0 : port); + + // trim the beginning "/" + while (path != null && path.startsWith("/")) { + path = path.substring(1); + } + this.path = path; + if (parameters == null) { + parameters = new HashMap(); + } else { + parameters = new HashMap(parameters); + } + this.parameters = Collections.unmodifiableMap(parameters); + + // build cache + parameterString = buildParameters(); + identityString = buildString(true); + fullString = identityString + (parameterString.length() > 0 ? '?' + parameterString : ""); + // no username and passwd + string = buildString(false) + (parameterString.length() > 0 ? '?' + parameterString : ""); + ip = StargateUtils.getIpByHost(host); + } + + /** + * Parse uri string + * + * @param uri URL string + * @return StargateURI instance + */ + public static StargateURI valueOf(String uri) { + if (uri == null || (uri = uri.trim()).length() == 0) { + throw new IllegalArgumentException("uri == null"); + } + String protocol = null; + String username = null; + String password = null; + String host = null; + int port = 0; + String path = null; + Map parameters = null; + int i = uri.indexOf("?"); // seperator between body and parameters + if (i >= 0) { + String[] parts = uri.substring(i + 1).split("\\&"); + parameters = new HashMap(); + for (String part : parts) { + part = part.trim(); + if (part.length() > 0) { + int j = part.indexOf('='); + if (j >= 0) { + parameters.put(part.substring(0, j), part.substring(j + 1)); + } else { + parameters.put(part, part); + } + } + } + uri = uri.substring(0, i); + } + i = uri.indexOf("://"); + if (i >= 0) { + if (i == 0) { + throw new IllegalStateException("uri missing protocol: \"" + uri + "\""); + } + protocol = uri.substring(0, i); + uri = uri.substring(i + 3); + } else { + // case: file:/path/to/file.txt + i = uri.indexOf(":/"); + if (i >= 0) { + if (i == 0) { + throw new IllegalStateException("uri missing protocol: \"" + uri + "\""); + } + protocol = uri.substring(0, i); + uri = uri.substring(i + 1); + } + } + + i = uri.indexOf("/"); + if (i >= 0) { + path = uri.substring(i + 1); + uri = uri.substring(0, i); + } + i = uri.indexOf("@"); + if (i >= 0) { + username = uri.substring(0, i); + int j = username.indexOf(":"); + if (j >= 0) { + password = username.substring(j + 1); + username = username.substring(0, j); + } + uri = uri.substring(i + 1); + } + i = uri.indexOf(":"); + if (i >= 0 && i < uri.length() - 1) { + port = Integer.parseInt(uri.substring(i + 1)); + uri = uri.substring(0, i); + } + if (uri.length() > 0) { + host = uri; + } + return new StargateURI(protocol, username, password, host, port, path, parameters); + } + + public String getProtocol() { + return protocol; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getHost() { + return host; + } + + public String getIp() { + return ip; + } + + public int getPort() { + return port; + } + + public String getAddress() { + return port <= 0 ? host : host + ":" + port; + } + + public String getPath() { + return path; + } + + public String getAbsolutePath() { + if (path != null && !path.startsWith("/")) { + return "/" + path; + } + return path; + } + + public StargateURI resetPath(String path) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public StargateURI resetHost(String host) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public StargateURI resetPort(int port) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public StargateURI resetProtocol(String protocol) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public StargateURI resetUsername(String username) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public StargateURI resetPassword(String password) { + return new StargateURI(protocol, username, password, host, port, path, getParameters()); + } + + public Map getParameters() { + return parameters; + } + + public String getParameterAndDecoded(String key) { + return getParameterAndDecoded(key, null); + } + + public String getParameterAndDecoded(String key, String defaultValue) { + return decode(getParameter(key, defaultValue)); + } + + /* + * 根据key获取参数值,如果不存在值,则去取default.key表示的值 + */ + public String getParameter(String key) { + String value = parameters.get(key); + if (value == null || value.length() == 0) { + value = parameters.get(StargateConstants.DEFAULT_KEY_PREFIX + key); + } + return value; + } + + public String getParameter(String key, String defaultValue) { + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + return value; + } + + public String[] getParameter(String key, String[] defaultValue) { + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + return StargateConstants.COMMA_SPLIT_PATTERN.split(value); + } + + public double getParameter(String key, double defaultValue) { + Number n = numbers.get(key); + if (n != null) { + return n.doubleValue(); + } + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + double d = Double.parseDouble(value); + numbers.put(key, d); + return d; + } + + public long getParameter(String key, long defaultValue) { + Number n = numbers.get(key); + if (n != null) { + return n.longValue(); + } + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + long l = Long.parseLong(value); + numbers.put(key, l); + return l; + } + + public int getParameter(String key, int defaultValue) { + Number n = numbers.get(key); + if (n != null) { + return n.intValue(); + } + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + int i = Integer.parseInt(value); + numbers.put(key, i); + return i; + } + + public boolean getParameter(String key, boolean defaultValue) { + String value = getParameter(key); + if (value == null || value.length() == 0) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + public double getPositiveParameter(String key, double defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + double value = getParameter(key, defaultValue); + if (value <= 0) { + return defaultValue; + } + return value; + } + + public long getPositiveParameter(String key, long defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + long value = getParameter(key, defaultValue); + if (value <= 0) { + return defaultValue; + } + return value; + } + + public int getPositiveParameter(String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + int value = getParameter(key, defaultValue); + if (value <= 0) { + return defaultValue; + } + return value; + } + + public boolean hasParameter(String key) { + String value = getParameter(key); + return value != null && value.length() > 0; + } + + public String getMethodParameterAndDecoded(String method, String key) { + return StargateURI.decode(getMethodParameter(method, key)); + } + + public String getMethodParameterAndDecoded(String method, String key, String defaultValue) { + return StargateURI.decode(getMethodParameter(method, key, defaultValue)); + } + + public String getMethodParameter(String method, String key) { + String value = parameters.get(method + "." + key); + if (value == null || value.length() == 0) { + return getParameter(key); + } + return value; + } + + public String getMethodParameter(String method, String key, String defaultValue) { + String value = getMethodParameter(method, key); + if (value == null || value.length() == 0) { + return defaultValue; + } + return value; + } + + public double getMethodParameter(String method, String key, double defaultValue) { + String methodKey = method + "." + key; + Number n = numbers.get(methodKey); + if (n != null) { + return n.intValue(); + } + String value = getMethodParameter(method, key); + if (value == null || value.length() == 0) { + return defaultValue; + } + double d = Double.parseDouble(value); + numbers.put(methodKey, d); + return d; + } + + public long getMethodParameter(String method, String key, long defaultValue) { + String methodKey = method + "." + key; + Number n = numbers.get(methodKey); + if (n != null) { + return n.intValue(); + } + String value = getMethodParameter(method, key); + if (value == null || value.length() == 0) { + return defaultValue; + } + long l = Long.parseLong(value); + numbers.put(methodKey, l); + return l; + } + + public int getMethodParameter(String method, String key, int defaultValue) { + String methodKey = method + "." + key; + Number n = numbers.get(methodKey); + if (n != null) { + return n.intValue(); + } + String value = getMethodParameter(method, key); + if (value == null || value.length() == 0) { + return defaultValue; + } + int i = Integer.parseInt(value); + numbers.put(methodKey, i); + return i; + } + + public boolean getMethodParameter(String method, String key, boolean defaultValue) { + String value = getMethodParameter(method, key); + if (value == null || value.length() == 0) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + public boolean hasMethodParameter(String method, String key) { + if (method == null) { + String suffix = "." + key; + for (String fullKey : parameters.keySet()) { + if (fullKey.endsWith(suffix)) { + return true; + } + } + return false; + } + if (key == null) { + String prefix = method + "."; + for (String fullKey : parameters.keySet()) { + if (fullKey.startsWith(prefix)) { + return true; + } + } + return false; + } + String value = getMethodParameter(method, key); + return value != null && value.length() > 0; + } + + /** + * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构建的使用Builder进行 + */ + public StargateURI addParameters(Map parameters) { + if (parameters == null || parameters.size() == 0) { + return this; + } + Map map = new HashMap(getParameters()); + map.putAll(parameters); + return new StargateURI(protocol, username, password, host, port, path, map); + } + + /** + * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构建的使用Builder进行 + */ + public StargateURI addParameters(String... pairs) { + return addParameters(StargateUtils.toStringMap(pairs)); + } + + /** + * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构造的使用Builder进行 + */ + public StargateURI addParameterString(String query) { + if (query == null || query.length() == 0) { + return this; + } + return addParameters(StargateUtils.parseQueryString(query)); + } + + /** + * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构造的使用Builder进行 调换一下顺序,以老的参数覆盖新的参数 + */ + public StargateURI addParametersIfAbsent(Map parameters) { + if (parameters == null || parameters.size() == 0) { + return this; + } + Map map = new HashMap(parameters); + map.putAll(getParameters()); + return new StargateURI(protocol, username, password, host, port, path, map); + } + + public StargateURI removeParameter(String key) { + if (key == null || key.length() == 0) { + return this; + } + return removeParameters(key); + } + + public StargateURI removeParameters(Collection keys) { + if (keys == null || keys.size() == 0) { + return this; + } + return removeParameters(keys.toArray(new String[0])); + } + + public StargateURI removeParameters(String... keys) { + if (keys == null || keys.length == 0) { + return this; + } + Map map = new HashMap(getParameters()); + for (String key : keys) { + map.remove(key); + } + if (map.size() == getParameters().size()) { + return this; + } + return new StargateURI(protocol, username, password, host, port, path, map); + } + + public StargateURI clearParameters() { + return new StargateURI(protocol, username, password, host, port, path, new HashMap()); + } + + @Override + public String toString() { + return string; + } + + public String toIdentityString() { + return identityString; + } + + public String toFullString() { + return fullString; + } + + public String toParameterString() { + return parameterString; + } + + private String buildParameters() { + StringBuilder buf = new StringBuilder(); + if (getParameters() != null && getParameters().size() > 0) { + boolean first = true; + for (Map.Entry entry : new TreeMap(getParameters()).entrySet()) { + if (entry.getKey() != null && entry.getKey().length() > 0) { + if (first) { + first = false; + } else { + buf.append("&"); + } + buf.append(entry.getKey()); + buf.append("="); + buf.append(entry.getValue() == null ? "" : entry.getValue().trim()); + } + } + } + return buf.toString(); + } + + private String buildString(boolean u) { + StringBuilder buf = new StringBuilder(); + if (protocol != null && protocol.length() > 0) { + buf.append(protocol); + buf.append("://"); + } + if (u && username != null && username.length() > 0) { + buf.append(username); + if (password != null && password.length() > 0) { + buf.append(":"); + buf.append(password); + } + buf.append("@"); + } + if (host != null && host.length() > 0) { + buf.append(host); + if (port > 0) { + buf.append(":"); + buf.append(port); + } + } + if (path != null && path.length() > 0) { + buf.append("/"); + buf.append(path); + } + return buf.toString(); + } + + public java.net.URL toJavaURL() { + try { + return new java.net.URL(toFullString()); + } catch (MalformedURLException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public InetSocketAddress toInetSocketAddress() { + return new InetSocketAddress(host, port); + } + + public String getServiceKey() { + String inf = getServiceName(); + if (inf == null) { + return null; + } + StringBuilder buf = new StringBuilder(); + String group = getParameter(StargateConstants.GROUP_KEY); + if (group != null && group.length() > 0) { + buf.append(group).append(":"); + } + buf.append(inf); + String version = getParameter(StargateConstants.VERSION_KEY); + if (version != null && version.length() > 0) { + buf.append(":").append(version); + } + return buf.toString(); + } + + public String getSimpleServiceKey() { + String inf = getServiceName(true); + if (inf == null) { + return null; + } + StringBuilder buf = new StringBuilder(); + String group = getParameter(StargateConstants.GROUP_KEY); + if (group != null && group.length() > 0) { + buf.append(group).append(":"); + } + buf.append(inf); + String version = getParameter(StargateConstants.VERSION_KEY); + if (version != null && version.length() > 0) { + buf.append(":").append(version); + } + return buf.toString(); + } + + public String getServiceName() { + return getServiceName(false); + } + + public String getServiceName(boolean simple) { + // for 格式化 fuck + String xx = getParameter(StargateConstants.INTERFACE_SIMPLE_KEY, path); + return simple ? xx : getParameter(StargateConstants.INTERFACE_KEY, path); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((host == null) ? 0 : host.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + port; + result = prime * result + ((protocol == null) ? 0 : protocol.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + StargateURI other = (StargateURI) obj; + if (host == null) { + if (other.host != null) { + return false; + } + } else if (!host.equals(other.host)) { + return false; + } + + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + + if (port != other.port) { + return false; + } + + if (protocol == null) { + return other.protocol == null; + } else { + return protocol.equals(other.protocol); + } + } + + public static String encode(String value) { + if (value == null || value.length() == 0) { + return ""; + } + try { + return URLEncoder.encode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static String decode(String value) { + if (value == null || value.length() == 0) { + return ""; + } + try { + return URLDecoder.decode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateUtils.java new file mode 100644 index 00000000..ef0d65d2 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/protocol/stargate/StargateUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.protocol.stargate; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * copy from Stargate 1.2.18 + *

+ * 专项服务于Stargate组件 + */ +public class StargateUtils { + + private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)"); + + private StargateUtils() { + } + + public static Map toStringMap(String... pairs) { + Map parameters = new HashMap(); + if (pairs.length > 0) { + if (pairs.length % 2 != 0) { + throw new IllegalArgumentException("pairs must be even."); + } + for (int i = 0; i < pairs.length; i = i + 2) { + parameters.put(pairs[i], pairs[i + 1]); + } + } + return parameters; + } + + public static String genUUID() { + return UUID.randomUUID().toString(); + } + + public static String getIpByHost(String hostName) { + try { + return InetAddress.getByName(hostName).getHostAddress(); + } catch (UnknownHostException e) { + return hostName; + } + } + + public static Map parseQueryString(String qs) { + if (qs == null || qs.length() == 0) { + return new HashMap(); + } + return parseKeyValuePair(qs, "\\&"); + } + + private static Map parseKeyValuePair(String str, String itemSeparator) { + String[] tmp = str.split(itemSeparator); + Map map = new HashMap(tmp.length); + for (String s : tmp) { + Matcher matcher = KVP_PATTERN.matcher(s); + if (!matcher.matches()) { + continue; + } + map.put(matcher.group(1), matcher.group(2)); + } + return map; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/BrpcPushProxy.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/BrpcPushProxy.java new file mode 100644 index 00000000..68fca18e --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/BrpcPushProxy.java @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.Validate; + +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.DefaultInterceptorChain; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.interceptor.ServerPushInterceptor; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.nshead.NSHeadMeta; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.utils.ProtobufUtils; + +import lombok.extern.slf4j.Slf4j; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * Created by huwenwei on 2017/4/25. + */ +@SuppressWarnings("unchecked") +@Slf4j +public class BrpcPushProxy implements MethodInterceptor { + + private static final Set notProxyMethodSet = new HashSet(); + + static { + notProxyMethodSet.add("getClass"); + notProxyMethodSet.add("hashCode"); + notProxyMethodSet.add("equals"); + notProxyMethodSet.add("clone"); + notProxyMethodSet.add("toString"); + notProxyMethodSet.add("notify"); + notProxyMethodSet.add("notifyAll"); + notProxyMethodSet.add("wait"); + notProxyMethodSet.add("finalize"); + } + + private RpcServer rpcServer; + private static Map rpcMethodMap = new HashMap(); + + /** + * 初始化时提前解析好method信息,在rpc交互时会更快。 + * + * @param rpcServer rpcServer + * @param clazz rpc接口类 + */ + protected BrpcPushProxy(RpcServer rpcServer, Class clazz) { + this.rpcServer = rpcServer; + // 检查 serve push 协议 + if (!(rpcServer.getProtocol() instanceof ServerPushProtocol)) { + throw new RpcException(" server protocol should be serverPushProtocl"); + } + + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + if (notProxyMethodSet.contains(method.getName())) { + log.debug("{}:{} does not need to proxy", + method.getDeclaringClass().getName(), method.getName()); + continue; + } + + Class[] oriTypes = method.getParameterTypes(); + if (oriTypes.length < 1) { + throw new IllegalArgumentException("number of arguments cannot be zero"); + } else if (!String.class.isAssignableFrom(oriTypes[0])) { + throw new IllegalArgumentException("first arguments must be clientName (String)"); + } else if (Future.class.isAssignableFrom(method.getReturnType()) + && !RpcCallback.class.isAssignableFrom(oriTypes[oriTypes.length - 1])) { + throw new IllegalArgumentException("returnType is Future, but last argument is not RpcCallback"); + } + // 转换为父接口 , 去掉第一个clientName参数,不传到client端 + Class[] paramTypesExcludeClientName = ArrayUtils.subarray(oriTypes, 1, oriTypes.length); + int paramLengthExcludeClientName = paramTypesExcludeClientName.length; + + Class[] actualArgTypes = paramTypesExcludeClientName; + if (paramLengthExcludeClientName >= 1) { // 如果有callback,则去掉callback,否则跟去掉clientName后的参数一致 + if (RpcCallback.class.isAssignableFrom(paramTypesExcludeClientName[paramLengthExcludeClientName - 1])) { + actualArgTypes = ArrayUtils.subarray(paramTypesExcludeClientName, 0, + paramTypesExcludeClientName.length - 1); + } + } + + Method syncMethod; + try { + syncMethod = method.getDeclaringClass().getMethod( + method.getName(), actualArgTypes); + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException("can not find sync method:" + method.getName()); + } + + RpcMethodInfo methodInfo; + ProtobufUtils.MessageType messageType = ProtobufUtils.getMessageType(syncMethod); + if (messageType == ProtobufUtils.MessageType.PROTOBUF) { + methodInfo = new ProtobufRpcMethodInfo(syncMethod); + } else if (messageType == ProtobufUtils.MessageType.JPROTOBUF) { + methodInfo = new JprotobufRpcMethodInfo(syncMethod); + } else { + methodInfo = new RpcMethodInfo(syncMethod); + } + + rpcMethodMap.put(method.getName(), methodInfo); + log.debug("client serviceName={}, methodName={}", + method.getDeclaringClass().getName(), method.getName()); + } + } + + public static T getProxy(RpcServer rpcServer, Class clazz) { + Enhancer en = new Enhancer(); + en.setSuperclass(clazz); + en.setCallback(new BrpcPushProxy(rpcServer, clazz)); + return (T) en.create(); + } + + // public BrpcPushProxy(RpcServer rpcServer) { + // this.rpcServer = rpcServer; + // timeoutTimer = new HashedWheelTimer(new CustomThreadFactory("timeout-timer-thread")); + // + // } + + /** + * server push 调用用户接口时候, 实际执行的方法 + * + * @param obj + * @param method + * @param args + * @param proxy + * + * @return + * + * @throws Throwable + */ + @Override + public Object intercept(Object obj, Method method, Object[] args, + MethodProxy proxy) throws Throwable { + Validate.notNull(rpcServer); + String methodName = method.getName(); + RpcMethodInfo rpcMethodInfo = rpcMethodMap.get(methodName); + if (rpcMethodInfo == null) { + log.debug("{}:{} does not need to proxy", + method.getDeclaringClass().getName(), methodName); + return proxy.invokeSuper(obj, args); + } + + // 转换为父接口 , 去掉第一个clientName参数,不传到client端 + Object[] actualArgs; + int argLength = args.length; + List argList = Arrays.asList(args); + argList = argList.subList(1, argLength); + argLength = argList.size(); + actualArgs = argList.toArray(); + + Request request = null; + Response response = null; + + List interceptors = null; + int readTimeout = 10 * 1000; + int writeTimeout = 10 * 1000; + // 区分 server端push还是client端发请求 + + request = rpcServer.getProtocol().createRequest(); + response = rpcServer.getProtocol().getResponse(); + request.setClientName((String) args[0]); + SPHead spHead = ((ServerPushProtocol) rpcServer.getProtocol()).createSPHead(); + spHead.setType(SPHead.TYPE_PUSH_REQUEST); + request.setSpHead(spHead); + request.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE.getNumber()); + interceptors = new ArrayList(); + ServerPushInterceptor serverPushInterceptor = new ServerPushInterceptor(); + serverPushInterceptor.setRpcServer(rpcServer); + interceptors.add(serverPushInterceptor); + + try { + + request.setTarget(obj); + request.setRpcMethodInfo(rpcMethodInfo); + request.setTargetMethod(rpcMethodInfo.getMethod()); + request.setServiceName(rpcMethodInfo.getServiceName()); + request.setMethodName(rpcMethodInfo.getMethodName()); + NSHeadMeta nsHeadMeta = rpcMethodInfo.getNsHeadMeta(); + NSHead nsHead = nsHeadMeta == null ? new NSHead() : new NSHead(0, nsHeadMeta.id(), nsHeadMeta.version(), + nsHeadMeta.provider(), 0); + request.setNsHead(nsHead); + + // parse request params + RpcCallback callback = null; + + if (argLength > 1) { + int startIndex = 0; + int endIndex = argLength - 1; + // 异步调用 + if (actualArgs[endIndex] instanceof RpcCallback) { + callback = (RpcCallback) actualArgs[endIndex]; + endIndex -= 1; + argLength -= 1; + } + + if (argLength <= 0) { + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, "invalid params"); + } + + Object[] sendArgs = new Object[argLength]; + for (int i = 0; startIndex <= endIndex; i++) { + sendArgs[i] = actualArgs[startIndex++]; + } + request.setArgs(sendArgs); + request.setCallback(callback); + } else { + // sync call + request.setArgs(actualArgs); + } + + if (RpcContext.isSet()) { + RpcContext rpcContext = RpcContext.getContext(); + // attachment + if (rpcContext.getRequestKvAttachment() != null) { + request.setKvAttachment(rpcContext.getRequestKvAttachment()); + } + if (rpcContext.getRequestBinaryAttachment() != null) { + request.setBinaryAttachment(rpcContext.getRequestBinaryAttachment()); + } + if (rpcContext.getLogId() != null) { + request.getNsHead().logId = rpcContext.getLogId(); + } + if (rpcContext.getServiceTag() != null) { + request.setServiceTag(rpcContext.getServiceTag()); + } + if (rpcContext.getReadTimeoutMillis() != null) { + request.setReadTimeoutMillis(rpcContext.getReadTimeoutMillis()); + } + if (rpcContext.getWriteTimeoutMillis() != null) { + request.setWriteTimeoutMillis(rpcContext.getWriteTimeoutMillis()); + } + rpcContext.reset(); + } + + if (request.getReadTimeoutMillis() == null) { + request.setReadTimeoutMillis(readTimeout); + } + if (request.getWriteTimeoutMillis() == null) { + request.setWriteTimeoutMillis(writeTimeout); + } + + InterceptorChain interceptorChain = new DefaultInterceptorChain(interceptors); + try { + interceptorChain.intercept(request, response); + if (response.getException() != null) { + throw new RpcException(response.getException()); + } + if (request.getCallback() != null) { + return response.getRpcFuture(); + } else { + return response.getResult(); + } + } catch (Exception ex) { + log.error("exception :", ex); + throw new RpcException(response.getException()); + } + } finally { + if (request != null) { + // release send buffer because we retain send buffer when send request. + request.release(); + } + } + } + + public Map getRpcMethodMap() { + return rpcMethodMap; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelManager.java new file mode 100644 index 00000000..3c629491 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelManager.java @@ -0,0 +1,91 @@ +package com.baidu.brpc.server; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.apache.commons.lang3.StringUtils; + +import com.baidu.brpc.server.push.PushChannelContextHolder; + +import io.netty.channel.Channel; +import io.netty.util.Attribute; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ChannelManager { + private static volatile ChannelManager instance; + private static ChannelStoreManager storeManager; + + private ReadWriteLock lock = new ReentrantReadWriteLock(); + private ChannelStoreManager innerStoreManager; + + public static void setStoreManager(ChannelStoreManager manager) { + storeManager = manager; + } + + public static ChannelManager getInstance() { + if (instance == null) { + synchronized (ChannelManager.class) { + if (instance == null) { + if (storeManager != null) { + instance = new ChannelManager(storeManager); + } else { + instance = new ChannelManager(new DefaultChannelStoreManager()); + } + } + } + } + return instance; + } + + private ChannelManager(ChannelStoreManager storeManager) { + this.innerStoreManager = storeManager; + } + + public void putChannel(String clientName, Channel channel) { + lock.writeLock().lock(); + try { + innerStoreManager.putChannel(clientName, channel); + } finally { + lock.writeLock().unlock(); + } + } + + public Channel getChannel(String clientName) { + if (log.isDebugEnabled()) { + for (Map.Entry> entry : innerStoreManager.getChannelMap().entrySet()) { + log.debug("participantName={}, channelNum={}", + entry.getKey(), + entry.getValue() == null ? 0 : entry.getValue().size()); + } + } + lock.readLock().lock(); + try { + return innerStoreManager.getChannel(clientName); + } finally { + lock.readLock().unlock(); + } + } + + public void removeChannel(Channel channel) { + + Attribute participant = channel.attr(PushChannelContextHolder.CLIENTNAME_KEY); + String participantName = participant.get(); + if (StringUtils.isNotBlank(participantName)) { + lock.writeLock().lock(); + try { + innerStoreManager.removeChannel(channel); + } finally { + lock.writeLock().unlock(); + } + } + } + + public Map> getChannelMap() { + return innerStoreManager.getChannelMap(); + } + + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelStoreManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelStoreManager.java new file mode 100644 index 00000000..0d118ef6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/ChannelStoreManager.java @@ -0,0 +1,16 @@ +package com.baidu.brpc.server; + +import io.netty.channel.Channel; + +import java.util.List; +import java.util.Map; + +public interface ChannelStoreManager { + void putChannel(String clientName, Channel channel); + + Channel getChannel(String clientName); + + void removeChannel(Channel channel); + + Map> getChannelMap(); +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/DefaultChannelStoreManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/DefaultChannelStoreManager.java new file mode 100644 index 00000000..302e0fff --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/DefaultChannelStoreManager.java @@ -0,0 +1,63 @@ +package com.baidu.brpc.server; + +import com.baidu.brpc.server.push.PushChannelContextHolder; +import io.netty.channel.Channel; +import io.netty.util.Attribute; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +@Slf4j +public class DefaultChannelStoreManager implements ChannelStoreManager { + private Map> channelMap = new HashMap>(); + private Set channelSet = new HashSet(); + private AtomicInteger index = new AtomicInteger(0); + + + @Override + public void putChannel(String clientName, Channel channel) { + if (!channelSet.contains(channel)) { + List channelList = channelMap.get(clientName); + if (channelList == null) { + channelList = new ArrayList(); + channelMap.put(clientName, channelList); + } + channelMap.get(clientName).add(channel); + } + } + + @Override + public Channel getChannel(String clientName) { + List channelList = channelMap.get(clientName); + if (channelList == null || channelList.size() == 0) { + log.info("no available connection for clientName={}", clientName); + return null; + } + int id = index.getAndIncrement() % channelList.size(); + Channel channel = channelList.get(id); + return channel; + } + + @Override + public void removeChannel(Channel channel) { + Attribute participant = channel.attr(PushChannelContextHolder.CLIENTNAME_KEY); + String participantName = participant.get(); + List channelList = channelMap.get(participantName); + channelList.remove(channel); + channelSet.remove(channel); + + } + + @Override + public Map> getChannelMap() { + return channelMap; + } + + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/HttpConstants.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/HttpConstants.java new file mode 100644 index 00000000..47be0cfe --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/HttpConstants.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.server; + +/** + * Http constant class. + * + * @author xiemalin + * @since 3.1.0 + */ +public class HttpConstants { + + /** The Constant LINE_BREAK. */ + public static final String LINE_BREAK = "
"; + + /** The Constant PRE_STARTS. */ + public static final String PRE_STARTS = "
";
+    
+    /** The Constant PRE_ENDS. */
+    public static final String PRE_ENDS = "
"; + + /** The Constant HTML_HEAD. */ + public static final String HTML_HEAD = ""; + + /** The Constant HTML_TAIL. */ + public static final String HTML_TAIL = ""; + + /** The Constant BOLD_FONT. */ + public static final String BOLD_FONT = ""; + + /** The Constant BOLD_FONT_END. */ + public static final String BOLD_FONT_END = ""; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/PushServerRpcFutureManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/PushServerRpcFutureManager.java new file mode 100644 index 00000000..385e0bf7 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/PushServerRpcFutureManager.java @@ -0,0 +1,38 @@ +package com.baidu.brpc.server; + +import com.baidu.brpc.client.FastFutureStore; +import com.baidu.brpc.client.RpcFuture; + +public class PushServerRpcFutureManager { + private static volatile PushServerRpcFutureManager instance; + private FastFutureStore pendingRpc; + + public static PushServerRpcFutureManager getInstance() { + if (instance == null) { + synchronized(PushServerRpcFutureManager.class) { + if (instance == null) { + instance = new PushServerRpcFutureManager(); + } + } + } + return instance; + } + + private PushServerRpcFutureManager() { + pendingRpc = FastFutureStore.getInstance(0); + } + + public long putRpcFuture(RpcFuture future) { + long correlationId = pendingRpc.put(future); + future.setCorrelationId(correlationId); + return correlationId; + } + + public RpcFuture getRpcFuture(Long logId) { + return pendingRpc.get(logId); + } + + public RpcFuture removeRpcFuture(Long logId) { + return pendingRpc.getAndRemove(logId); + } +} \ No newline at end of file diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServer.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServer.java new file mode 100644 index 00000000..f1b5f0bd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServer.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.channels.ClosedChannelException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.client.AsyncAwareFuture; +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.interceptor.ServerInvokeInterceptor; +import com.baidu.brpc.interceptor.ServerTraceInterceptor; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.naming.NamingServiceFactoryManager; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolManager; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.server.handler.RpcServerChannelIdleHandler; +import com.baidu.brpc.server.handler.RpcServerHandler; +import com.baidu.brpc.server.push.RegisterServiceImpl; +import com.baidu.brpc.spi.ExtensionLoaderManager; +import com.baidu.brpc.thread.BrpcBossGroupInstance; +import com.baidu.brpc.thread.BrpcWorkServerThreadPoolInstance; +import com.baidu.brpc.thread.BrpcWorkerGroupInstance; +import com.baidu.brpc.thread.ClientTimeoutTimerInstance; +import com.baidu.brpc.thread.ShutDownManager; +import com.baidu.brpc.utils.BrpcConstants; +import com.baidu.brpc.utils.CollectionUtils; +import com.baidu.brpc.utils.CustomThreadFactory; +import com.baidu.brpc.utils.NetUtils; +import com.baidu.brpc.utils.ThreadPool; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollChannelOption; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollMode; +import io.netty.channel.epoll.EpollServerSocketChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.Getter; + +/** + * Created by wenweihu86 on 2017/4/24. + */ +@Getter +public class RpcServer { + private static final Logger LOG = LoggerFactory.getLogger(RpcServer.class); + + private RpcServerOptions rpcServerOptions = new RpcServerOptions(); + + /** + * host to bind + */ + private String host; + + /** + * port to bind + */ + private int port; + + /** + * netty bootstrap + */ + private ServerBootstrap bootstrap; + + /** + * netty io thread pool + */ + private EventLoopGroup bossGroup; + // netty io thread pool + private EventLoopGroup workerGroup; + private List interceptors = new ArrayList(); + private Protocol protocol; + private ThreadPool threadPool; + private List customThreadPools = new ArrayList(); + private NamingService namingService; + private List serviceList = new ArrayList(); + private List registerInfoList = new ArrayList(); + private ServerStatus serverStatus; + private AtomicBoolean stop = new AtomicBoolean(false); + + private Timer timeoutTimer; + + public RpcServer(int port) { + this(null, port, new RpcServerOptions(), null); + } + + public RpcServer(String host, int port) { + this(host, port, new RpcServerOptions(), null); + } + + public RpcServer(int port, RpcServerOptions options) { + this(null, port, options, null); + } + + public RpcServer(String host, int port, RpcServerOptions options) { + this(host, port, options, null); + } + + public RpcServer(int port, RpcServerOptions options, List interceptors) { + this(null, port, options, interceptors); + } + + public RpcServer(String host, int port, + final RpcServerOptions options, + List interceptors) { + this.host = host; + this.port = port; + if (options != null) { + try { + this.rpcServerOptions.copyFrom(options); + } catch (Exception ex) { + LOG.warn("init options failed, so use default"); + } + } + if (interceptors != null) { + this.interceptors.addAll(interceptors); + } + ExtensionLoaderManager.getInstance().loadAllExtensions(rpcServerOptions.getEncoding()); + if (StringUtils.isNotBlank(rpcServerOptions.getNamingServiceUrl())) { + BrpcURL url = new BrpcURL(rpcServerOptions.getNamingServiceUrl()); + NamingServiceFactory namingServiceFactory = NamingServiceFactoryManager.getInstance() + .getNamingServiceFactory(url.getSchema()); + this.namingService = namingServiceFactory.createNamingService(url); + } + // find protocol + if (rpcServerOptions.getProtocolType() != null) { + this.protocol = ProtocolManager.getInstance().getProtocol(rpcServerOptions.getProtocolType()); + } + bootstrap = new ServerBootstrap(); + if (rpcServerOptions.isGlobalThreadPoolSharing()) { + threadPool = BrpcWorkServerThreadPoolInstance.getOrCreateInstance(rpcServerOptions.getWorkThreadNum()); + } else { + threadPool = new ThreadPool(rpcServerOptions.getWorkThreadNum(), + new CustomThreadFactory("server-work-thread")); + } + + if (rpcServerOptions.getIoEventType() == BrpcConstants.IO_EVENT_NETTY_EPOLL) { + if (rpcServerOptions.isGlobalThreadPoolSharing()) { + bossGroup = BrpcBossGroupInstance.getOrCreateEpollInstance(rpcServerOptions.getAcceptorThreadNum()); + workerGroup = BrpcWorkerGroupInstance.getOrCreateEpollInstance(rpcServerOptions.getAcceptorThreadNum()); + } else { + bossGroup = new EpollEventLoopGroup(rpcServerOptions.getAcceptorThreadNum(), + new CustomThreadFactory("server-acceptor-thread")); + workerGroup = new EpollEventLoopGroup(rpcServerOptions.getIoThreadNum(), + new CustomThreadFactory("server-io-thread")); + } + ((EpollEventLoopGroup) bossGroup).setIoRatio(100); + ((EpollEventLoopGroup) workerGroup).setIoRatio(100); + bootstrap.channel(EpollServerSocketChannel.class); + bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); + bootstrap.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); + LOG.info("use netty epoll edge trigger mode"); + } else { + if (rpcServerOptions.isGlobalThreadPoolSharing()) { + bossGroup = BrpcBossGroupInstance.getOrCreateNioInstance(rpcServerOptions.getAcceptorThreadNum()); + workerGroup = BrpcWorkerGroupInstance.getOrCreateNioInstance(rpcServerOptions.getAcceptorThreadNum()); + } else { + bossGroup = new NioEventLoopGroup(rpcServerOptions.getAcceptorThreadNum(), + new CustomThreadFactory("server-acceptor-thread")); + workerGroup = new NioEventLoopGroup(rpcServerOptions.getIoThreadNum(), + new CustomThreadFactory("server-io-thread")); + } + ((NioEventLoopGroup) bossGroup).setIoRatio(100); + ((NioEventLoopGroup) workerGroup).setIoRatio(100); + bootstrap.channel(NioServerSocketChannel.class); + LOG.info("use jdk nio event mode"); + } + + bootstrap.option(ChannelOption.SO_BACKLOG, rpcServerOptions.getBacklog()); + bootstrap.childOption(ChannelOption.SO_KEEPALIVE, rpcServerOptions.isKeepAlive()); + bootstrap.childOption(ChannelOption.TCP_NODELAY, rpcServerOptions.isTcpNoDelay()); + bootstrap.childOption(ChannelOption.SO_REUSEADDR, true); + bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); + bootstrap.childOption(ChannelOption.SO_LINGER, rpcServerOptions.getSoLinger()); + bootstrap.childOption(ChannelOption.SO_SNDBUF, rpcServerOptions.getSendBufferSize()); + bootstrap.childOption(ChannelOption.SO_RCVBUF, rpcServerOptions.getReceiveBufferSize()); + final RpcServerHandler rpcServerHandler = new RpcServerHandler(RpcServer.this); + ChannelInitializer initializer = new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ch.pipeline().addLast( + "idleStateAwareHandler", new IdleStateHandler( + rpcServerOptions.getReaderIdleTime(), + rpcServerOptions.getWriterIdleTime(), + rpcServerOptions.getKeepAliveTime())); + ch.pipeline().addLast("idle", new RpcServerChannelIdleHandler()); + ch.pipeline().addLast(rpcServerHandler); + } + }; + bootstrap.group(bossGroup, workerGroup).childHandler(initializer); + + this.serverStatus = new ServerStatus(this); + + // register shutdown hook to jvm + ShutDownManager.getInstance(); + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + RpcServer.this.shutdown(); + } + })); + + timeoutTimer = ClientTimeoutTimerInstance.getOrCreateInstance(); + + // 注册serverPush的内部服务接口 + if (protocol instanceof ServerPushProtocol) { + registerService(new RegisterServiceImpl()); + } + } + + public void registerService(Object service) { + registerService(service, null, null, null); + } + + public void registerService(Object service, NamingOptions namingOptions) { + registerService(service, null, namingOptions, null); + } + + public void registerService(Object service, Class targetClass, NamingOptions namingOptions) { + registerService(service, targetClass, namingOptions, null); + } + + public void registerService(Object service, RpcServerOptions serverOptions) { + registerService(service, null, null, serverOptions); + } + + /** + * register service which can be accessed by client + * + * @param service the service object which implement rpc interface. + * @param namingOptions register center info + * @param serverOptions service own custom RpcServerOptions + * if not null, the service will not use the shared thread pool. + */ + public void registerService(Object service, Class targetClass, NamingOptions namingOptions, + RpcServerOptions serverOptions) { + serviceList.add(service); + RegisterInfo registerInfo = null; + if (namingOptions != null) { + registerInfo = new RegisterInfo(namingOptions); + } else { + registerInfo = new RegisterInfo(); + } + if (targetClass != null) { + registerInfo.setInterfaceName(targetClass.getInterfaces()[0].getName()); + } else { + registerInfo.setInterfaceName(service.getClass().getInterfaces()[0].getName()); + } + registerInfo.setHost(NetUtils.getLocalAddress().getHostAddress()); + registerInfo.setPort(port); + ServiceManager serviceManager = ServiceManager.getInstance(); + ThreadPool customThreadPool = threadPool; + if (serverOptions != null) { + customThreadPool = new ThreadPool(serverOptions.getWorkThreadNum(), + new CustomThreadFactory(service.getClass().getSimpleName() + "-work-thread")); + customThreadPools.add(customThreadPool); + } + + if (targetClass == null) { + serviceManager.registerService(service, customThreadPool); + } else { + serviceManager.registerService(targetClass, service, customThreadPool); + } + registerInfoList.add(registerInfo); + } + + public void start() { + this.interceptors.add(0, new ServerTraceInterceptor()); + this.interceptors.add(new ServerInvokeInterceptor()); + try { + // 判断是否在jarvis环境,若是jarvis环境则以环境变量port为准,否则以用户自定义的port为准 + if (rpcServerOptions.getJarvisPortName() != null) { + if (System.getenv(rpcServerOptions.getJarvisPortName()) != null) { + this.port = Integer.valueOf(System.getenv(rpcServerOptions.getJarvisPortName())); + } + } + ChannelFuture channelFuture; + if (null != host) { + channelFuture = bootstrap.bind(host, port); + } else { + channelFuture = bootstrap.bind(port); + } + channelFuture.sync(); + if (port == 0 && channelFuture.channel() != null) { + // update port to the actual value in case the server in started on a random port + Channel channel = channelFuture.channel(); + SocketAddress localAddress = channel.localAddress(); + if (localAddress instanceof InetSocketAddress) { + this.port = ((InetSocketAddress) localAddress).getPort(); + } + } + if (namingService != null) { + for (RegisterInfo registerInfo : registerInfoList) { + registerInfo.setPort(port); + namingService.register(registerInfo); + } + } + } catch (InterruptedException e) { + LOG.error("server failed to start, {}", e.getMessage()); + } + if (LOG.isInfoEnabled()) { + LOG.info("server started on port={} success", port); + } + } + + public void shutdown() { + if (stop.compareAndSet(false, true)) { + if (namingService != null) { + for (RegisterInfo registerInfo : registerInfoList) { + namingService.unregister(registerInfo); + } + } + if (bossGroup != null && !rpcServerOptions.isGlobalThreadPoolSharing()) { + bossGroup.shutdownGracefully().syncUninterruptibly(); + } + if (workerGroup != null && !rpcServerOptions.isGlobalThreadPoolSharing()) { + workerGroup.shutdownGracefully().syncUninterruptibly(); + } + if (threadPool != null && !rpcServerOptions.isGlobalThreadPoolSharing()) { + threadPool.stop(); + } + if (CollectionUtils.isNotEmpty(customThreadPools)) { + LOG.info("clean customized thread pool"); + for (ThreadPool pool : customThreadPools) { + pool.stop(); + } + } + } + } + + public boolean isShutdown() { + return stop.get(); + } + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public AsyncAwareFuture sendServerPush(Request request) { + Channel channel = request.getChannel(); + ChannelInfo orCreateServerChannelInfo = ChannelInfo.getOrCreateServerChannelInfo(channel); // todo + // create RpcFuture object + RpcFuture rpcFuture = new ServerPushRpcFuture(); + rpcFuture.setRpcMethodInfo(request.getRpcMethodInfo()); + rpcFuture.setCallback(request.getCallback()); + rpcFuture.setChannelInfo(orCreateServerChannelInfo); + // generate correlationId + final long correlationId = PushServerRpcFutureManager.getInstance().putRpcFuture(rpcFuture); + + request.setCorrelationId(correlationId); + request.getSpHead().setCorrelationId(correlationId); + // read write timeout + final long readTimeout = request.getReadTimeoutMillis(); + final long writeTimeout = request.getWriteTimeoutMillis(); + Timeout timeout = timeoutTimer.newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + long timeoutCorrelationId = correlationId; + PushServerRpcFutureManager rpcFutureManager = PushServerRpcFutureManager.getInstance(); + RpcFuture rpcFuture = rpcFutureManager.removeRpcFuture(timeoutCorrelationId); + + if (rpcFuture != null) { + long elapseTime = System.currentTimeMillis() - rpcFuture.getStartTime(); + String errMsg = String.format("request timeout,correlationId=%d,ip=%s,port=%d,elapse=%dms", + timeoutCorrelationId, "?", port, elapseTime); + LOG.info(errMsg); + Response response = protocol.createResponse(); + response.setException(new RpcException(RpcException.TIMEOUT_EXCEPTION, errMsg)); + response.setRpcFuture(rpcFuture); + rpcFuture.handleResponse(response); + } else { + LOG.error("timeout rpc is missing, correlationId={}", timeoutCorrelationId); + throw new RpcException(RpcException.UNKNOWN_EXCEPTION, "timeout rpc is missing"); + } + } + }, readTimeout, TimeUnit.MILLISECONDS); + + // set the missing parameters + rpcFuture.setTimeout(timeout); + try { + // netty will release the send buffer after sent. + // we retain here, so it can be used when rpc retry. + request.retain(); + + ByteBuf byteBuf = protocol.encodeRequest(request); + ChannelFuture sendFuture = channel.writeAndFlush(byteBuf); + sendFuture.awaitUninterruptibly(writeTimeout); + if (!sendFuture.isSuccess()) { + if (!(sendFuture.cause() instanceof ClosedChannelException)) { + LOG.warn("send request failed, channelActive={}, ex=", + channel.isActive(), sendFuture.cause()); + } + String errMsg = String.format("send request failed, channelActive=%b, ex=%s", + channel.isActive(), sendFuture.cause().getMessage()); + throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg); + } + } catch (Exception ex) { + timeout.cancel(); + if (ex instanceof RpcException) { + throw (RpcException) ex; + } else { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex.getMessage(), ex); + } + } + + return rpcFuture; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServerOptions.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServerOptions.java new file mode 100644 index 00000000..924b8076 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/RpcServerOptions.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server; + +import com.baidu.brpc.utils.BrpcConstants; + +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +/** + * Created by wenweihu86 on 2017/4/24. + */ +@Setter +@Getter +@ToString +@NoArgsConstructor +public class RpcServerOptions { + // The keep alive + private boolean keepAlive = true; + private boolean tcpNoDelay = true; + // so linger + private int soLinger = 5; + // backlog + private int backlog = 1024; + // receive buffer size + private int receiveBufferSize = 1024 * 64; + // send buffer size + private int sendBufferSize = 1024 * 64; + /** + * an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE} + * will be triggered when no read was performed for the specified period of time. + * Specify {@code 0} to disable. + */ + private int readerIdleTime = 60; + /** + * an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE} + * will be triggered when no write was performed for the specified period of time. + * Specify {@code 0} to disable. + */ + private int writerIdleTime = 60; + // keepAlive时间(second) + private int keepAliveTime = 5; + // acceptor threads, default use Netty default value + private int acceptorThreadNum = 1; + // io threads, default use Netty default value + private int ioThreadNum = Runtime.getRuntime().availableProcessors(); + // real work threads + private int workThreadNum = Runtime.getRuntime().availableProcessors(); + /** + * io event type, netty or jdk + */ + private int ioEventType = BrpcConstants.IO_EVENT_JDK; + // The max size + private int maxSize = Integer.MAX_VALUE; + + private int maxTryTimes = 1; + + public void setProtocolType(Integer protocolType) { + this.protocolType = protocolType; + } + + // server protocol type + private Integer protocolType; + private String encoding = "utf-8"; + // bns port name when deploys on Jarvis environment + private String jarvisPortName; + // naming service url + private String namingServiceUrl = ""; + // share global thread pool between multi rpcServer + private boolean globalThreadPoolSharing = false; + + public RpcServerOptions(RpcServerOptions options) { + this.copyFrom(options); + } + + public void copyFrom(RpcServerOptions options) { + this.acceptorThreadNum = options.acceptorThreadNum; + this.backlog = options.backlog; + this.encoding = options.encoding; + this.ioThreadNum = options.ioThreadNum; + this.jarvisPortName = options.jarvisPortName; + this.keepAlive = options.keepAlive; + this.keepAliveTime = options.keepAliveTime; + this.maxSize = options.maxSize; + this.namingServiceUrl = options.namingServiceUrl; + this.protocolType = options.protocolType; + this.readerIdleTime = options.readerIdleTime; + this.receiveBufferSize = options.receiveBufferSize; + this.sendBufferSize = options.sendBufferSize; + this.soLinger = options.soLinger; + this.tcpNoDelay = options.tcpNoDelay; + this.workThreadNum = options.workThreadNum; + this.writerIdleTime = options.writerIdleTime; + this.globalThreadPoolSharing = options.globalThreadPoolSharing; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerPushRpcFuture.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerPushRpcFuture.java new file mode 100644 index 00000000..e39f034e --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerPushRpcFuture.java @@ -0,0 +1,31 @@ +package com.baidu.brpc.server; + +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Response; + +public class ServerPushRpcFuture extends RpcFuture { + + public void handleConnection(Response response) { + this.response = response; + this.endTime = System.currentTimeMillis(); + timeout.cancel(); + latch.countDown(); + isDone = true; + } + + public void handleResponse(Response response) { + handleConnection(response); + if (isAsync()) { + setRpcContext(); + if (response == null) { + callback.fail(new RpcException(RpcException.SERVICE_EXCEPTION, "internal error")); + } else if (response.getResult() != null) { + callback.success(response.getResult()); + } else { + callback.fail(response.getException()); + } + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerStatus.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerStatus.java new file mode 100644 index 00000000..b8aed5b6 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServerStatus.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.server; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.utils.ThreadPool; +import java.util.Map; + +import static com.baidu.brpc.server.HttpConstants.BOLD_FONT; +import static com.baidu.brpc.server.HttpConstants.BOLD_FONT_END; +import static com.baidu.brpc.server.HttpConstants.HTML_HEAD; +import static com.baidu.brpc.server.HttpConstants.LINE_BREAK; +import static com.baidu.brpc.server.HttpConstants.PRE_STARTS; + +/** + * Server status. + * + * @author xiemalin + * @since 3.1.0 + */ +public class ServerStatus { + /** The Constant SECONDS_IN_HOUR. */ + private static final int SECONDS_IN_HOUR = 3600; + + /** The Constant SECONDS_IN_DAY. */ + private static final int SECONDS_IN_DAY = 86400; + + /** The start time. */ + private long startTime; + + /** The rpc server. */ + private RpcServer rpcServer; + + public ServerStatus(RpcServer rpcServer) { + this.rpcServer = rpcServer; + this.startTime = System.currentTimeMillis(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder ret = new StringBuilder(); + ret.append(HTML_HEAD); + ret.append("Server online: ").append(getOnlineDuration(startTime)).append(LINE_BREAK); + ret.append("RPC port:").append(rpcServer.getPort()).append(LINE_BREAK); + + ret.append("Http management port:").append(rpcServer.getPort()).append(LINE_BREAK); + ret.append("Compress enabled(Gzip Snappy)").append(LINE_BREAK); + ret.append("Attachment enabled").append(LINE_BREAK); + + ThreadPool.StatInfo threadPoolInfo = rpcServer.getThreadPool().getStatInfo(); + ret.append("--------------Thread status----------------").append(LINE_BREAK); + ret.append("Thread count:").append(threadPoolInfo.getThreadNum()).append(LINE_BREAK); + ret.append("Queue capacity:").append(threadPoolInfo.getDefaultQueueCapacity()).append(LINE_BREAK); + ret.append("Producer queue size:").append(threadPoolInfo.getProducerQueueSize()).append(LINE_BREAK); + ret.append("Consumer queue size:").append(threadPoolInfo.getConsumerQueueSize()).append(LINE_BREAK); + ret.append(LINE_BREAK).append(LINE_BREAK); + + ret.append(PRE_STARTS); + ret.append("--------------properties info(").append(RpcServerOptions.class.getDeclaredFields().length) + .append(")----------------").append(LINE_BREAK); + ret.append(rpcServer.getRpcServerOptions()); + + ret.append(LINE_BREAK).append(LINE_BREAK); + + ServiceManager serviceManager = ServiceManager.getInstance(); + Map serviceMap = serviceManager.getServiceMap(); + ret.append("--------------RPC service list(").append(serviceMap.size()).append(") ----------------") + .append(LINE_BREAK); + + for (Map.Entry entry : serviceMap.entrySet()) { + ret.append(BOLD_FONT).append("Service name:").append(entry.getValue().getServiceName()) + .append(LINE_BREAK); + ret.append("Method name:").append(entry.getValue().getMethodName()).append(BOLD_FONT_END) + .append(LINE_BREAK); + + ret.append("Request IDL:").append(LINE_BREAK).append( + ((Class) entry.getValue().getInputClasses()[0]).getName()) + .append(LINE_BREAK); + ret.append("Response IDL:").append(LINE_BREAK).append( + ((Class) entry.getValue().getOutputClass()).getName()) + .append(LINE_BREAK); + + ret.append(LINE_BREAK); + } + + ret.append(LINE_BREAK).append(LINE_BREAK); + + return ret.toString(); + } + + /** + * Gets the online duration. + * + * @param startTime the start time + * @return the online duration + */ + private String getOnlineDuration(long startTime) { + StringBuilder ret = new StringBuilder(); + long ms = (System.currentTimeMillis() - startTime) / 1000; + + long days = ms / SECONDS_IN_DAY; + long hours = (ms % SECONDS_IN_DAY) / SECONDS_IN_HOUR; + long seconds = ((ms % SECONDS_IN_DAY) % SECONDS_IN_HOUR); + + ret.append(days).append(" days ").append(hours).append(" hours ").append(seconds).append(" seconds"); + + return ret.toString(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/ServiceManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServiceManager.java new file mode 100644 index 00000000..f3e2d7ec --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/ServiceManager.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.utils.ProtobufUtils; +import com.baidu.brpc.utils.ThreadPool; + +/** + * Created by huwenwei on 2017/4/25. + */ +@SuppressWarnings("unchecked") +public class ServiceManager { + private static final Logger LOG = LoggerFactory.getLogger(ServiceManager.class); + private static volatile ServiceManager instance; + + private Map serviceMap; + + public static ServiceManager getInstance() { + if (instance == null) { + synchronized (ServiceManager.class) { + if (instance == null) { + instance = new ServiceManager(); + } + } + } + return instance; + } + + private ServiceManager() { + this.serviceMap = new HashMap(); + } + + public void registerService(Object service, ThreadPool threadPool) { + Class[] interfaces = service.getClass().getInterfaces(); + if (interfaces.length != 1) { + LOG.error("service must implement one interface only"); + throw new RuntimeException("service must implement one interface only"); + } + Class clazz = interfaces[0]; + Method[] methods = clazz.getDeclaredMethods(); + registerService(methods, service, threadPool); + } + + public void registerService(Class targetClass, Object service, ThreadPool threadPool) { + Class[] interfaces = targetClass.getInterfaces(); + if (interfaces.length != 1) { + LOG.error("service must implement one interface only"); + throw new RuntimeException("service must implement one interface only"); + } + Class clazz = interfaces[0]; + Method[] methods = clazz.getDeclaredMethods(); + registerService(methods, service, threadPool); + } + + public void registerPushService(Object service) { + registerService(service); + } + + public void registerService(Object service) { + Class[] interfaces = service.getClass().getInterfaces(); + if (interfaces.length != 1) { + LOG.error("service must implement one interface only"); + throw new RuntimeException("service must implement one interface only"); + } + Class clazz = interfaces[0]; + Method[] methods = clazz.getDeclaredMethods(); + ServiceManager serviceManager = ServiceManager.getInstance(); + for (Method method : methods) { + RpcMethodInfo serviceInfo = new RpcMethodInfo(method); + String serviceName = method.getDeclaringClass().getName(); + String methodName = method.getName(); + serviceInfo.setServiceName(serviceName); + serviceInfo.setMethodName(methodName); + serviceInfo.setTarget(service); + serviceInfo.setMethod(method); + serviceManager.registerService(serviceInfo); + LOG.info("register service, serviceName={}, methodName={}", + serviceInfo.getServiceName(), serviceInfo.getMethodName()); + } + } + + protected void registerService(Method[] methods, Object service, ThreadPool threadPool) { + for (Method method : methods) { + RpcMethodInfo methodInfo; + ProtobufUtils.MessageType messageType = ProtobufUtils.getMessageType(method); + if (messageType == ProtobufUtils.MessageType.PROTOBUF) { + methodInfo = new ProtobufRpcMethodInfo(method); + } else if (messageType == ProtobufUtils.MessageType.JPROTOBUF) { + methodInfo = new JprotobufRpcMethodInfo(method); + } else { + methodInfo = new RpcMethodInfo(method); + } + methodInfo.setTarget(service); + methodInfo.setThreadPool(threadPool); + registerService(methodInfo); + LOG.info("register service, serviceName={}, methodName={}", + methodInfo.getServiceName(), methodInfo.getMethodName()); + } + } + + protected void registerService(RpcMethodInfo methodInfo) { + String key = buildServiceKey(methodInfo.getServiceName(), methodInfo.getMethodName()); + serviceMap.put(key, methodInfo); + } + + public RpcMethodInfo getService(String serviceName, String methodName) { + String key = buildServiceKey(serviceName, methodName); + return serviceMap.get(key); + } + + public RpcMethodInfo getService(String serviceMethodName) { + return serviceMap.get(serviceMethodName); + } + + public Map getServiceMap() { + return serviceMap; + } + + + private String buildServiceKey(String serviceName, String methodName) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(serviceName.toLowerCase()).append(".").append(methodName.toLowerCase()); + return stringBuilder.toString(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CounterCurrentLimiter.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CounterCurrentLimiter.java new file mode 100644 index 00000000..4026ce11 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CounterCurrentLimiter.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.currentlimit; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.extern.slf4j.Slf4j; + +/** + * a simple counter implement of current limit algorithm + * + * @author wangjiayin@baidu.com + * @since 2018/11/26 + */ +@Slf4j +public class CounterCurrentLimiter implements CurrentLimiter { + + private final int timeIntervalMs = 200; + + private final int maxReqPerInterval; + + private AtomicInteger count = new AtomicInteger(0); + + private Timer timer = new HashedWheelTimer(new CustomThreadFactory("counterLimiter-timer-thread")); + + /** + * constructor + * + * @param maxQps max query per second + */ + public CounterCurrentLimiter(int maxQps) { + if (maxQps <= 0) { + throw new IllegalArgumentException("maxQps must be positive!"); + } + this.maxReqPerInterval = maxQps / (1000 / timeIntervalMs); + timer.newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) { + count.set(0); + timer.newTimeout(this, timeIntervalMs, TimeUnit.MILLISECONDS); + } + }, timeIntervalMs, TimeUnit.MILLISECONDS); + } + + @Override + public boolean isAllowable(Request request) { + return count.getAndIncrement() <= maxReqPerInterval; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CurrentLimiter.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CurrentLimiter.java new file mode 100644 index 00000000..b84112e5 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CurrentLimiter.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.currentlimit; + +import com.baidu.brpc.protocol.Request; + +/** + * current limit interface in brpc server + * according to brpc c++, if limit is reached, + * rpc server will return error to rpc client immediately rather than queue up + * + * @author wangjiayin@baidu.com + * @since 2018/11/26 + */ +public interface CurrentLimiter { + + boolean isAllowable(Request request); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/TokenBucketCurrentLimiter.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/TokenBucketCurrentLimiter.java new file mode 100644 index 00000000..e171ae93 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/TokenBucketCurrentLimiter.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.currentlimit; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.extern.slf4j.Slf4j; + +/** + * Token bucket algorithm Advantage: allow certain burst traffic, and flow control is smoother + * + * @author wangjiayin@baidu.com + * @since 2018/11/26 + */ +@Slf4j +public class TokenBucketCurrentLimiter implements CurrentLimiter { + + // the bucket size, namely the max concurrency + private final int bucketSize; + // Time interval for put tokens into the bucket + private final int timeIntervalMs = 200; + // Number of tokens added to the bucket per time period + private int tokenPerInterval; + // current token num in the bucket + private AtomicInteger currentToken; + + private Timer timer = new HashedWheelTimer(new CustomThreadFactory("tokenBucketLimiter-timer-thread")); + + public TokenBucketCurrentLimiter(int bucketSize, int tokenInputRate) { + if (bucketSize <= 0 || tokenInputRate <= 0) { + throw new IllegalArgumentException("bucketSize and rate must be positive!"); + } + this.bucketSize = bucketSize; + this.tokenPerInterval = tokenInputRate / (1000 / timeIntervalMs); + if (this.tokenPerInterval == 0) { + this.tokenPerInterval = 1; + } + this.currentToken = new AtomicInteger(bucketSize); + timer.newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + supply(); + timer.newTimeout(this, timeIntervalMs, TimeUnit.MILLISECONDS); + } + }, timeIntervalMs, TimeUnit.MILLISECONDS); + } + + /** + * get a token if there's no more token in the bucket, return immediately + * + * @return if success + */ + private boolean acquire() { + while (true) { + int curToken = currentToken.get(); + if (curToken <= 0) { + return false; + } + if (currentToken.compareAndSet(curToken, curToken - 1)) { + return true; + } + + } + } + + /** + * put some tokens into the bucket + */ + private void supply() { + // 这里就不加锁了 + if (currentToken.getAndAdd(tokenPerInterval) > bucketSize) { + currentToken.set(bucketSize); + } + } + + @Override + public boolean isAllowable(Request request) { + return this.acquire(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/DecodeWorkTask.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/DecodeWorkTask.java new file mode 100644 index 00000000..037a11e7 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/DecodeWorkTask.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.handler; + +import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION; +import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH; +import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE; +import static io.netty.handler.codec.http.HttpResponseStatus.OK; +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +import com.baidu.brpc.client.RpcFuture; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.http.BrpcHttpResponseEncoder; +import com.baidu.brpc.protocol.http.HttpRpcProtocol; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushPacket; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.ServerStatus; +import com.baidu.brpc.utils.ThreadPool; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderValues; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Setter +@Getter +@AllArgsConstructor +public class DecodeWorkTask implements Runnable { + private RpcServer rpcServer; + private Object packet; + private Protocol protocol; + private ChannelHandlerContext ctx; + + @Override + public void run() { + if (protocol instanceof HttpRpcProtocol) { + FullHttpRequest fullHttpRequest = (FullHttpRequest) packet; + try { + if (fullHttpRequest.uri().equals("/favicon.ico")) { + FullHttpResponse fullHttpResponse = + new DefaultFullHttpResponse(HTTP_1_1, OK); + fullHttpResponse.headers().set(CONTENT_LENGTH, 0); + if (HttpUtil.isKeepAlive(fullHttpRequest)) { + fullHttpResponse.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE); + } + BrpcHttpResponseEncoder encoder = new BrpcHttpResponseEncoder(); + ByteBuf responseByteBuf = encoder.encode(fullHttpResponse); + ChannelFuture f = ctx.channel().writeAndFlush(responseByteBuf); + if (!HttpUtil.isKeepAlive(fullHttpRequest)) { + f.addListener(ChannelFutureListener.CLOSE); + } + return; + } else if (fullHttpRequest.uri().equals("/") || fullHttpRequest.uri().equals("/status")) { + ServerStatus serverStatus = rpcServer.getServerStatus(); + + byte[] statusBytes = serverStatus.toString().getBytes("UTF-8"); + FullHttpResponse fullHttpResponse = + new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(statusBytes)); + fullHttpResponse.headers().set(CONTENT_TYPE, "text/html"); + fullHttpResponse.headers().set(CONTENT_LENGTH, fullHttpResponse.content().readableBytes()); + if (HttpUtil.isKeepAlive(fullHttpRequest)) { + fullHttpResponse.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); + } + BrpcHttpResponseEncoder encoder = new BrpcHttpResponseEncoder(); + ByteBuf responseByteBuf = encoder.encode(fullHttpResponse); + ChannelFuture f = ctx.channel().writeAndFlush(responseByteBuf); + if (!HttpUtil.isKeepAlive(fullHttpRequest)) { + f.addListener(ChannelFutureListener.CLOSE); + } + return; + } + } catch (Exception ex) { + log.warn("send status info response failed:", ex); + return; + } + } else if (protocol instanceof ServerPushProtocol) { + SPHead spHead = ((ServerPushPacket) packet).getSpHead(); + if (spHead.getType() == SPHead.TYPE_PUSH_RESPONSE) { + processClientResponse(); + return; + } + } + + Request request = null; + Response response = protocol.createResponse(); + try { + request = protocol.decodeRequest(packet); + } catch (Exception ex) { + // throw request + log.warn("decode request failed:", ex); + response.setException(ex); + } finally { + if (request != null && request.getException() != null) { + response.setException(request.getException()); + } + } + + if (request == null || response.getException() != null) { + try { + ByteBuf byteBuf = protocol.encodeResponse(request, response); + ChannelFuture channelFuture = ctx.channel().writeAndFlush(byteBuf); + protocol.afterResponseSent(request, response, channelFuture); + } catch (Exception ex) { + log.warn("send response failed:", ex); + } + return; + } + + ThreadPool threadPool = request.getRpcMethodInfo().getThreadPool(); + ServerWorkTask workTask = new ServerWorkTask(rpcServer, protocol, request, response, ctx); + if (threadPool == rpcServer.getThreadPool()) { + // service run in the current thread + workTask.run(); + } else { + // service run in individual thread + threadPool.submit(workTask); + } + } + + /** + * 处理client的返回response + */ + public void processClientResponse() { + Response response; + try { + response = ((ServerPushProtocol) protocol).decodeServerPushResponse(packet, ctx); + } catch (Exception e) { + log.warn("decode response failed:", e); + return; + } + if (response.getRpcFuture() != null) { + log.debug("handle response, logId={}", response.getLogId()); + RpcFuture future = response.getRpcFuture(); + future.handleResponse(response); + } else { + log.warn("rpcFuture is null, logId={}", response.getLogId()); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerChannelIdleHandler.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerChannelIdleHandler.java new file mode 100644 index 00000000..c77faf6a --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerChannelIdleHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.handler; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 关闭空闲连接 + * + * @author wenweihu86 + */ +public class RpcServerChannelIdleHandler extends ChannelDuplexHandler { + private static final Logger LOG = LoggerFactory.getLogger(RpcServerChannelIdleHandler.class); + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object event) throws Exception { + if (event instanceof IdleStateEvent) { + IdleStateEvent e = (IdleStateEvent) event; + if (e.state() == IdleState.ALL_IDLE) { + // if no read and write for period time, close current channel + LOG.debug("channel={} ip={} is idle for period time, close now.", + ctx.channel(), ctx.channel().remoteAddress()); + ctx.close(); + } else { + LOG.debug("idle on channel[{}]:{}", e.state(), ctx.channel()); + } + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerHandler.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerHandler.java new file mode 100644 index 00000000..69e1bb29 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/RpcServerHandler.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.handler; + +import java.io.IOException; +import java.util.List; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.exceptions.BadSchemaException; +import com.baidu.brpc.exceptions.NotEnoughDataException; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.exceptions.TooBigDataException; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.ProtocolManager; +import com.baidu.brpc.server.ChannelManager; +import com.baidu.brpc.server.RpcServer; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.unix.Errors; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by huwenwei on 2017/4/25. + */ +@ChannelHandler.Sharable +@Slf4j +public class RpcServerHandler extends SimpleChannelInboundHandler { + + private RpcServer rpcServer; + + public RpcServerHandler(RpcServer rpcServer) { + this.rpcServer = rpcServer; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ChannelInfo channelInfo = ChannelInfo.getOrCreateServerChannelInfo(ctx.channel()); + channelInfo.setProtocol(rpcServer.getProtocol()); + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, Object in) throws Exception { + ChannelInfo channelInfo = ChannelInfo.getServerChannelInfo(ctx.channel()); + ByteBuf msg = (ByteBuf) in; + int len = msg.readableBytes(); + if (len > 0) { + channelInfo.getRecvBuf().addBuffer(msg.retain()); + DecodeWorkTask[] tasks = new DecodeWorkTask[64]; + int i = 0; + while (channelInfo.getRecvBuf().readableBytes() > 0) { + try { + Object packet = decodeHeader(ctx, channelInfo, channelInfo.getRecvBuf()); + DecodeWorkTask task = new DecodeWorkTask(rpcServer, packet, channelInfo.getProtocol(), ctx); + tasks[i++] = task; + if (i == 64) { + rpcServer.getThreadPool().submit(tasks, 0, i); + i = 0; + } + } catch (NotEnoughDataException ex1) { + break; + } catch (TooBigDataException ex2) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex2); + } catch (BadSchemaException ex3) { + throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, ex3); + } + } + if (i > 0) { + rpcServer.getThreadPool().submit(tasks, 0, i); + + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (ctx.channel().isActive() + && !(cause instanceof Errors.NativeIoException) + && !(cause instanceof IOException)) { + log.info("service exception, ex={}", cause.getMessage()); + } + log.debug("meet exception, may be connection is closed, msg={}", cause.getMessage()); + log.debug("remove from channel map"); + ChannelManager.getInstance().removeChannel(ctx.channel()); + ctx.close(); + } + + /** + * 尝试用各个协议解析header。 + * 所目前所有的协议至少都需要12字节,以第一个协议抛出not enough data异常后,就不重试剩余协议了。 + * 只要有一个协议抛too big data异常,就不再重试剩余协议。 + * + * @param channelInfo channel信息,包含protocol + * @param compositeByteBuf 输入buffer + * + * @return 反序列化后packet + * + * @throws NotEnoughDataException + * @throws TooBigDataException + * @throws BadSchemaException + */ + private Object decodeHeader(ChannelHandlerContext ctx, + ChannelInfo channelInfo, + DynamicCompositeByteBuf compositeByteBuf) + throws NotEnoughDataException, TooBigDataException, BadSchemaException { + Protocol protocol = channelInfo.getProtocol(); + if (protocol != null) { + return protocol.decode(ctx, compositeByteBuf, true); + } + ProtocolManager protocolManager = ProtocolManager.getInstance(); + List protocols = protocolManager.getCoexistenceProtocols(); + int protocolSize = protocolManager.getCoexistenceProtocolSize(); + for (int i = 0; i < protocolSize; i++) { + Protocol protocol1 = protocols.get(i); + try { + Object packet = protocol1.decode(ctx, compositeByteBuf, true); + channelInfo.setProtocol(protocol1); + return packet; + } catch (BadSchemaException ex3) { + // 遇到bad schema继续重试。 + continue; + } + } + throw new BadSchemaException("bad schema"); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + log.debug("channel is in active, remove from channel map"); + ChannelManager.getInstance().removeChannel(ctx.channel()); + ctx.fireChannelInactive(); + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/ServerWorkTask.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/ServerWorkTask.java new file mode 100644 index 00000000..c3a5fcdf --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/handler/ServerWorkTask.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.handler; + +import java.lang.reflect.InvocationTargetException; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.interceptor.DefaultInterceptorChain; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.protocol.Protocol; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.push.SPHead; +import com.baidu.brpc.protocol.push.ServerPushProtocol; +import com.baidu.brpc.server.RpcServer; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Setter +@Getter +@AllArgsConstructor +public class ServerWorkTask implements Runnable { + private RpcServer rpcServer; + private Protocol protocol; + private Request request; + private Response response; + private ChannelHandlerContext ctx; + + @Override + public void run() { + RpcContext rpcContext = null; + if (request != null) { + request.setChannel(ctx.channel()); + rpcContext = RpcContext.getContext(); + rpcContext.setRemoteAddress(ctx.channel().remoteAddress()); + rpcContext.setChannel(ctx.channel()); + + if (request.getBinaryAttachment() != null + || request.getKvAttachment() != null) { + if (request.getBinaryAttachment() != null) { + rpcContext.setRequestBinaryAttachment(request.getBinaryAttachment()); + } + if (request.getKvAttachment() != null) { + rpcContext.setRequestKvAttachment(request.getKvAttachment()); + } + } + + response.setLogId(request.getLogId()); + response.setCorrelationId(request.getCorrelationId()); + response.setCompressType(request.getCompressType()); + response.setException(request.getException()); + response.setRpcMethodInfo(request.getRpcMethodInfo()); + } + + if (response.getException() == null) { + try { + InterceptorChain interceptorChain = new DefaultInterceptorChain(rpcServer.getInterceptors()); + interceptorChain.intercept(request, response); + if (RpcContext.isSet()) { + rpcContext = RpcContext.getContext(); + if (rpcContext.getResponseBinaryAttachment() != null + && rpcContext.getResponseBinaryAttachment().isReadable()) { + response.setBinaryAttachment(rpcContext.getResponseBinaryAttachment()); + } + if (rpcContext.getResponseKvAttachment() != null + && !rpcContext.getResponseKvAttachment().isEmpty()) { + response.setKvAttachment(rpcContext.getResponseKvAttachment()); + } + } + } catch (Throwable ex) { + String errorMsg = String.format("failed to execute interceptor chain, msg=%s", ex.getMessage()); + log.warn(errorMsg, ex); + response.setException(ex); + } + } + + if (!request.isOneWay()) { + try { + ByteBuf byteBuf = protocol.encodeResponse(request, response); + ChannelFuture channelFuture = ctx.channel().writeAndFlush(byteBuf); + protocol.afterResponseSent(request, response, channelFuture); + } catch (Exception ex) { + log.warn("send response failed:", ex); + } + } + + if (rpcContext != null) { + if (rpcContext.getRequestBinaryAttachment() != null + && rpcContext.getRequestBinaryAttachment().refCnt() > 0) { + rpcContext.getRequestBinaryAttachment().release(); + } + rpcContext.reset(); + } + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/push/PushChannelContextHolder.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/PushChannelContextHolder.java new file mode 100644 index 00000000..7c7892f3 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/PushChannelContextHolder.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.server.push; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.util.AttributeKey; + +public class PushChannelContextHolder { + + public static final AttributeKey CLIENTNAME_KEY = AttributeKey.valueOf("clientName"); + private static final ThreadLocal CURRENT_CHANNEL = new ThreadLocal(); + + public static void setCurrentChannel(ChannelHandlerContext ctx) { + CURRENT_CHANNEL.set(ctx); + } + + public static ChannelHandlerContext getCurrentChannel() { + return CURRENT_CHANNEL.get(); + } + + public static void clear() { + CURRENT_CHANNEL.remove(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterService.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterService.java new file mode 100644 index 00000000..d09d6973 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterService.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.server.push; + +/** + * 用于serverpush 注册client + */ +public interface RegisterService { + + /** + * 注册和保存clientName + * + * @param clientName + */ + Response registerClient(String clientName); + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterServiceImpl.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterServiceImpl.java new file mode 100644 index 00000000..a9457cbd --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/RegisterServiceImpl.java @@ -0,0 +1,29 @@ +package com.baidu.brpc.server.push; + +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.server.ChannelManager; + +import io.netty.channel.Channel; +import io.netty.util.Attribute; + +public class RegisterServiceImpl implements RegisterService { + + private static final Logger LOG = LoggerFactory.getLogger(RegisterServiceImpl.class); + + public Response registerClient(String clientName) { + LOG.debug("invoke registerClient::clientName = [{}]", clientName); + RpcContext context = RpcContext.getContext(); + Channel channel = context.getChannel(); + Validate.notNull(channel, "rpc context channel cannot be null"); + Attribute clientInfo = channel.attr(PushChannelContextHolder.CLIENTNAME_KEY); + clientInfo.set(clientName); + ChannelManager.getInstance().putChannel(clientName, channel); + LOG.info("register channel success, Name={}, channel={}", + clientName, channel.remoteAddress().toString()); + return Response.success(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/server/push/Response.java b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/Response.java new file mode 100644 index 00000000..0c3e1aaa --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/server/push/Response.java @@ -0,0 +1,20 @@ +package com.baidu.brpc.server.push; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Response { + public int code; + public String message; + + public Response(int code, String message) { + this.code = code; + this.message = message; + } + + public static Response success() { + return new Response(0, null); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/spi/ExtensionLoaderManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/spi/ExtensionLoaderManager.java new file mode 100644 index 00000000..6b763798 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/spi/ExtensionLoaderManager.java @@ -0,0 +1,80 @@ +package com.baidu.brpc.spi; + +import com.baidu.brpc.client.loadbalance.LoadBalanceFactory; +import com.baidu.brpc.client.loadbalance.LoadBalanceManager; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.naming.NamingServiceFactoryManager; +import com.baidu.brpc.protocol.ProtocolFactory; +import com.baidu.brpc.protocol.ProtocolManager; + +import java.util.*; + +public class ExtensionLoaderManager { + private static volatile ExtensionLoaderManager instance; + + public static ExtensionLoaderManager getInstance() { + if (instance == null) { + synchronized (ExtensionLoaderManager.class) { + if (instance == null) { + instance = new ExtensionLoaderManager(); + } + } + } + return instance; + } + + private Object loadLock = new Object(); + private Boolean isLoaded = false; + + /** + * load all extensions with java spi + */ + public void loadAllExtensions(String encoding) { + if (!isLoaded) { + synchronized (loadLock) { + if (!isLoaded) { + loadNamingService(); + loadProtocol(encoding); + loadLoadBalance(); + + isLoaded = true; + } + } + } + } + + public void loadNamingService() { + NamingServiceFactoryManager manager = NamingServiceFactoryManager.getInstance(); + ServiceLoader namingServiceFactories = ServiceLoader.load(NamingServiceFactory.class); + for (NamingServiceFactory namingServiceFactory : namingServiceFactories) { + manager.registerNamingServiceFactory(namingServiceFactory); + } + } + + public void loadProtocol(String encoding) { + ProtocolManager protocolManager = ProtocolManager.getInstance(); + ServiceLoader protocolFactories = ServiceLoader.load(ProtocolFactory.class); + List protocolFactoryList = new ArrayList(); + for (ProtocolFactory protocolFactory : protocolFactories) { + protocolFactoryList.add(protocolFactory); + } + Collections.sort(protocolFactoryList, new Comparator() { + @Override + public int compare(ProtocolFactory o1, ProtocolFactory o2) { + return o1.getPriority() - o2.getPriority(); + } + }); + for (ProtocolFactory protocolFactory : protocolFactoryList) { + protocolManager.registerProtocol(protocolFactory, encoding); + } + } + + public void loadLoadBalance() { + LoadBalanceManager loadBalanceManager = LoadBalanceManager.getInstance(); + ServiceLoader loadBalanceFactories = ServiceLoader.load(LoadBalanceFactory.class); + for (LoadBalanceFactory loadBalanceFactory : loadBalanceFactories) { + loadBalanceManager.registerLoadBalanceFactory(loadBalanceFactory); + } + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcBossGroupInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcBossGroupInstance.java new file mode 100644 index 00000000..7e80838c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcBossGroupInstance.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; + +/** + * client & server io thread pool single instance + */ + +public class BrpcBossGroupInstance { + + private static volatile EpollEventLoopGroup epollThreadPool; + + private static volatile NioEventLoopGroup nioThreadPool; + + private BrpcBossGroupInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateEpollInstance(int threadNum) { + if (epollThreadPool == null) { + synchronized(BrpcBossGroupInstance.class) { + if (epollThreadPool == null) { + epollThreadPool = new EpollEventLoopGroup(threadNum, + new CustomThreadFactory("server-acceptor-thread")); + + } + } + } + return epollThreadPool; + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateNioInstance(int threadNum) { + if (nioThreadPool == null) { + synchronized(BrpcBossGroupInstance.class) { + if (nioThreadPool == null) { + nioThreadPool = new NioEventLoopGroup(threadNum, + new CustomThreadFactory("server-acceptor-thread")); + + } + } + } + return nioThreadPool; + } + + public static NioEventLoopGroup getNioInstance() { + return nioThreadPool; + } + + public static EpollEventLoopGroup getEpollInstance() { + return epollThreadPool; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcIoThreadPoolInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcIoThreadPoolInstance.java new file mode 100644 index 00000000..5a602430 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcIoThreadPoolInstance.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; + +/** + * client & server io thread pool single instance + */ + +public class BrpcIoThreadPoolInstance { + + private static volatile EpollEventLoopGroup epollThreadPool; + + private static volatile NioEventLoopGroup nioThreadPool; + + private BrpcIoThreadPoolInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateEpollInstance(int threadNum) { + if (epollThreadPool == null) { + synchronized (BrpcIoThreadPoolInstance.class) { + if (epollThreadPool == null) { + epollThreadPool = new EpollEventLoopGroup(threadNum, + new CustomThreadFactory("brpc-io-thread")); + + } + } + } + return epollThreadPool; + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateNioInstance(int threadNum) { + if (nioThreadPool == null) { + synchronized(BrpcIoThreadPoolInstance.class) { + if (nioThreadPool == null) { + nioThreadPool = new NioEventLoopGroup(threadNum, + new CustomThreadFactory("brpc-io-thread")); + + } + } + } + return nioThreadPool; + } + + public static NioEventLoopGroup getNioInstance() { + return nioThreadPool; + } + + public static EpollEventLoopGroup getEpollInstance() { + return epollThreadPool; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkClientThreadPoolInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkClientThreadPoolInstance.java new file mode 100644 index 00000000..c52746cc --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkClientThreadPoolInstance.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; +import com.baidu.brpc.utils.ThreadPool; + +/** + * client & server work thread pool single instance + */ +public class BrpcWorkClientThreadPoolInstance { + + private static volatile ThreadPool workThreadPool; + + private static String name = "brpc-work-thread"; + + private BrpcWorkClientThreadPoolInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static ThreadPool getOrCreateInstance(int threadNum) { + + if (workThreadPool == null) { + synchronized(BrpcWorkClientThreadPoolInstance.class) { + if (workThreadPool == null) { + workThreadPool = new ThreadPool(threadNum, + new CustomThreadFactory(name)); + } + } + } + + return workThreadPool; + } + + public static ThreadPool getInstance() { + return workThreadPool; + + } + + public static String getName() { + return name; + } + + public static void setName(String name) { + BrpcWorkClientThreadPoolInstance.name = name; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkServerThreadPoolInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkServerThreadPoolInstance.java new file mode 100644 index 00000000..47073688 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkServerThreadPoolInstance.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; +import com.baidu.brpc.utils.ThreadPool; + +/** + * client & server work thread pool single instance + */ +public class BrpcWorkServerThreadPoolInstance { + + private static volatile ThreadPool workThreadPool; + + private static String name = "brpc-server-work-thread"; + + private BrpcWorkServerThreadPoolInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static ThreadPool getOrCreateInstance(int threadNum) { + + if (workThreadPool == null) { + synchronized(BrpcWorkServerThreadPoolInstance.class) { + if (workThreadPool == null) { + workThreadPool = new ThreadPool(threadNum, + new CustomThreadFactory(name)); + } + } + } + + return workThreadPool; + } + + public static ThreadPool getInstance() { + return workThreadPool; + + } + + public static String getName() { + return name; + } + + public static void setName(String name) { + BrpcWorkServerThreadPoolInstance.name = name; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkerGroupInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkerGroupInstance.java new file mode 100644 index 00000000..89e8aeec --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/BrpcWorkerGroupInstance.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; + +/** + * client & server io thread pool single instance + */ + +public class BrpcWorkerGroupInstance { + + private static volatile EpollEventLoopGroup epollThreadPool; + + private static volatile NioEventLoopGroup nioThreadPool; + + private BrpcWorkerGroupInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateEpollInstance(int threadNum) { + if (epollThreadPool == null) { + synchronized(BrpcWorkerGroupInstance.class) { + if (epollThreadPool == null) { + epollThreadPool = new EpollEventLoopGroup(threadNum, + new CustomThreadFactory("server-io-thread")); + + } + } + } + return epollThreadPool; + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static EventLoopGroup getOrCreateNioInstance(int threadNum) { + if (nioThreadPool == null) { + synchronized(BrpcWorkerGroupInstance.class) { + if (nioThreadPool == null) { + nioThreadPool = new NioEventLoopGroup(threadNum, + new CustomThreadFactory("server-io-thread")); + + } + } + } + return nioThreadPool; + } + + public static NioEventLoopGroup getNioInstance() { + return nioThreadPool; + } + + public static EpollEventLoopGroup getEpollInstance() { + return epollThreadPool; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientCallBackThreadPoolInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientCallBackThreadPoolInstance.java new file mode 100644 index 00000000..c8602ff9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientCallBackThreadPoolInstance.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ClientCallBackThreadPoolInstance { + + private static volatile ExecutorService callbackThreadPool; + + private ClientCallBackThreadPoolInstance() { + + } + + /** + * threadNum only works when thread pool instance create in the first time + */ + public static ExecutorService getOrCreateInstance(int threadNum) { + if (callbackThreadPool == null) { + synchronized (ClientCallBackThreadPoolInstance.class) { + if (callbackThreadPool == null) { + callbackThreadPool = Executors.newFixedThreadPool(threadNum, + new CustomThreadFactory("invalid-channel-callback-thread")); + } + } + } + + return callbackThreadPool; + } + + public static ExecutorService getInstance() { + return callbackThreadPool; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientHealthCheckTimerInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientHealthCheckTimerInstance.java new file mode 100644 index 00000000..6ccd01d0 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientHealthCheckTimerInstance.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; + +public class ClientHealthCheckTimerInstance { + + private static volatile Timer healthCheckTimer; + + private ClientHealthCheckTimerInstance() { + + } + + public static Timer getOrCreateInstance() { + + if (healthCheckTimer == null) { + synchronized (ClientHealthCheckTimerInstance.class) { + if (healthCheckTimer == null) { + healthCheckTimer = + new HashedWheelTimer(new CustomThreadFactory("health-check-timer-thread")); + } + } + } + + return healthCheckTimer; + } + + public static Timer getInstance() { + + return healthCheckTimer; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientTimeoutTimerInstance.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientTimeoutTimerInstance.java new file mode 100644 index 00000000..467bac4c --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ClientTimeoutTimerInstance.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import com.baidu.brpc.utils.CustomThreadFactory; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; + +public class ClientTimeoutTimerInstance { + + private static volatile Timer timeoutTimer; + + private ClientTimeoutTimerInstance() { + + } + + public static Timer getOrCreateInstance() { + + if (timeoutTimer == null) { + synchronized (ClientTimeoutTimerInstance.class) { + if (timeoutTimer == null) { + timeoutTimer = new HashedWheelTimer(new CustomThreadFactory("timeout-timer-thread")); + } + } + } + + return timeoutTimer; + } + + public static Timer getInstance() { + + return timeoutTimer; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/thread/ShutDownManager.java b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ShutDownManager.java new file mode 100644 index 00000000..f8782bef --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/thread/ShutDownManager.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.thread; + +import java.util.concurrent.ExecutorService; + +import com.baidu.brpc.utils.ThreadPool; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.Timer; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ShutDownManager { + + private static volatile ShutDownManager clientShutDownManager; + + static { + // do clean work when jvm shut down + + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + log.info("Brpc do clean work..."); + shutdownGlobalThreadPools(); + + } + })); + } + + public static void shutdownGlobalThreadPools() { + log.info("invoke shutdownGlobalThreadPools"); + EventLoopGroup ioThread = BrpcIoThreadPoolInstance.getEpollInstance(); + EventLoopGroup nioInstance = BrpcIoThreadPoolInstance.getNioInstance(); + ThreadPool clientWorkThreadPool = BrpcWorkClientThreadPoolInstance.getInstance(); + ThreadPool serverWorkThreadPool = BrpcWorkServerThreadPoolInstance.getInstance(); + + EpollEventLoopGroup epollBossGroup = BrpcBossGroupInstance.getEpollInstance(); + NioEventLoopGroup nioBossGroup = BrpcBossGroupInstance.getNioInstance(); + EpollEventLoopGroup epollWorkerGroup = BrpcWorkerGroupInstance.getEpollInstance(); + NioEventLoopGroup nioWorkerGroup = BrpcWorkerGroupInstance.getNioInstance(); + ExecutorService clientCallBackThread = ClientCallBackThreadPoolInstance.getInstance(); + Timer clientHealthCheckerTimer = ClientHealthCheckTimerInstance.getInstance(); + Timer clientTimeOutTimer = ClientTimeoutTimerInstance.getInstance(); + + if (clientCallBackThread != null) { + clientCallBackThread.shutdownNow(); + } + if (ioThread != null) { + ioThread.shutdownGracefully(); + } + if (clientWorkThreadPool != null) { + clientWorkThreadPool.stop(); + } + if (nioInstance != null) { + nioInstance.shutdownGracefully(); + } + if (epollBossGroup != null) { + epollBossGroup.shutdownGracefully(); + } + if (nioBossGroup != null) { + nioBossGroup.shutdownGracefully(); + } + if (epollWorkerGroup != null) { + epollWorkerGroup.shutdownGracefully(); + } + if (nioWorkerGroup != null) { + nioWorkerGroup.shutdownGracefully(); + } + if (clientHealthCheckerTimer != null) { + clientHealthCheckerTimer.stop(); + } + if (clientTimeOutTimer != null) { + clientTimeOutTimer.stop(); + } + if (serverWorkThreadPool != null) { + serverWorkThreadPool.stop(); + } + } + + private ShutDownManager() { + + } + + public static ShutDownManager getInstance() { + + if (clientShutDownManager == null) { + synchronized(ShutDownManager.class) { + if (clientShutDownManager == null) { + clientShutDownManager = new ShutDownManager(); + } + } + } + return clientShutDownManager; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/BoundedQueue.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/BoundedQueue.java new file mode 100644 index 00000000..06f604ee --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/BoundedQueue.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.utils; + +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Iterator; +import java.util.Queue; + +public class BoundedQueue implements Queue { + private int capacity; + private int size; + private ArrayDeque queue; + + public BoundedQueue(int capacity) { + this.capacity = capacity; + this.size = 0; + queue = new ArrayDeque(capacity); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + public final boolean isFull() { + return size == capacity; + } + + @Override + public boolean contains(Object o) { + return queue.contains(o); + } + + @Override + public Iterator iterator() { + return queue.iterator(); + } + + @Override + public Object[] toArray() { + return queue.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return queue.toArray(a); + } + + @Override + public boolean add(E e) { + if (isFull()) { + queue.pollFirst(); + size--; + } + queue.addLast(e); + size++; + return true; + } + + @Override + public boolean containsAll(Collection c) { + return queue.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + int inputSize = c.size(); + if (inputSize > capacity) { + throw new IllegalArgumentException( + "Size of added which is " + inputSize + " is larger " + "than capacity=" + capacity); + } + int toPop = Math.max(0, inputSize - remainingCapacity()); + for (int i = 0; i < toPop; ++i) { + queue.pollFirst(); + } + size -= toPop; + for (E e : c) { + queue.addLast(e); + } + size += inputSize; + return true; + } + + public boolean addAll(E[] c, int offset, int len) { + if (len > capacity) { + throw new IllegalArgumentException( + "Size of added which is " + len + " is larger " + "than capacity=" + capacity); + } + int toPop = Math.max(0, len - remainingCapacity()); + for (int i = 0; i < toPop; ++i) { + queue.pollFirst(); + } + size -= toPop; + int last = offset + len; + for (int i = offset; i < last; i++) { + queue.addLast(c[i]); + } + size += len; + return true; + } + + @Override + public boolean removeAll(Collection c) { + boolean modified = queue.removeAll(c); + if (modified) { + size = queue.size(); + return true; + } + return false; + } + + @Override + public boolean retainAll(Collection c) { + boolean modified = queue.retainAll(c); + if (modified) { + size = queue.size(); + return true; + } + return false; + } + + @Override + public void clear() { + queue.clear(); + size = 0; + } + + @Override + public boolean offer(E e) { + return add(e); + } + + @Override + public boolean remove(Object o) { + if (queue.remove(o)) { + size--; + return true; + } + return false; + } + + @Override + public E remove() { + E e = queue.removeFirst(); + size--; + return e; + } + + @Override + public E poll() { + E e = queue.pollFirst(); + if (e != null) { + size--; + } + return e; + } + + @Override + public E element() { + return queue.element(); + } + + @Override + public E peek() { + return queue.peekFirst(); + } + + public int remainingCapacity() { + return capacity - size; + } + + public E pop() { + E e = queue.pop(); + size--; + return e; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/BrpcConstants.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/BrpcConstants.java new file mode 100644 index 00000000..e3e7fdb9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/BrpcConstants.java @@ -0,0 +1,6 @@ +package com.baidu.brpc.utils; + +public class BrpcConstants { + public static int IO_EVENT_JDK = 1; + public static int IO_EVENT_NETTY_EPOLL = 2; +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/CollectionUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/CollectionUtils.java new file mode 100644 index 00000000..92b60870 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/CollectionUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.utils; + +import java.util.Collection; + +/** + * Utility methods for {@link Collection} instances. + * + * @author guohaoice@gmail.com + */ +public final class CollectionUtils { + + /** + * Null-safe check if the specified collection is empty. + * + * @param collection the collection to check, may be null + * @return true if empty or null + */ + public static boolean isEmpty(Collection collection) { + return null == collection || collection.isEmpty(); + } + + /** + * Null-safe check if the specified collection is not empty. + * + * @param collection the collection to check, may be null + * @return true if non-null and non-empty + */ + public static boolean isNotEmpty(Collection collection) { + return !isEmpty(collection); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/CustomThreadFactory.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/CustomThreadFactory.java new file mode 100644 index 00000000..453d5084 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/CustomThreadFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import io.netty.util.concurrent.FastThreadLocalThread; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by huwenwei on 2017/9/29. + */ +@Slf4j +public class CustomThreadFactory implements ThreadFactory { + + private AtomicInteger threadNumber = new AtomicInteger(1); + private String namePrefix; + private ThreadGroup group; + + public CustomThreadFactory(String namePrefix) { + SecurityManager s = System.getSecurityManager(); + this.group = (s != null) ? s.getThreadGroup() : + Thread.currentThread().getThreadGroup(); + this.namePrefix = namePrefix + "-"; + } + + @Override + public Thread newThread(Runnable r) { + String name = namePrefix + threadNumber.getAndIncrement(); + Thread t = new FastThreadLocalThread(group, r, name, 0); + t.setDaemon(true); + t.setPriority(Thread.NORM_PRIORITY); + log.info("create thread:{}", name); + return t; + } + +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/GsonUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/GsonUtils.java new file mode 100644 index 00000000..aae264d5 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/GsonUtils.java @@ -0,0 +1,58 @@ +package com.baidu.brpc.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import java.lang.reflect.Type; + +public class GsonUtils { + private static Gson gson; + + static { + gson = getGB().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); + } + + private static GsonBuilder getGB() { + return new GsonBuilder(); + } + + public static T fromJson(String json, Class classOfT) { + return gson.fromJson(json, classOfT); + } + + public static T fromJson(String json, Type typeOfT) { + return gson.fromJson(json, typeOfT); + } + + public static T fromJson(JsonElement jsonElement, Class classOfT) { + return gson.fromJson(jsonElement, classOfT); + } + + public static T fromJson(JsonElement jsonElement, Type typeOfT) { + return gson.fromJson(jsonElement, typeOfT); + } + + public static String toJson(Object o) { + return gson.toJson(o); + } + + public static String toPrettyPrintJson(Object o) { + return getGB().setPrettyPrinting().create().toJson(o); + } + + public Boolean isValidJson(String str) { + try { + gson.fromJson(str, Object.class); + return true; + } catch (JsonSyntaxException e) { + return false; + } + } + + public static JsonElement parseJson(String json) { + return new JsonParser().parse(json); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/IOUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/IOUtils.java new file mode 100644 index 00000000..912ddaed --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/IOUtils.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class IOUtils { + private static final int BUFFER_SIZE = 256; + + public static byte[] readInputStream(InputStream inputStream) throws IOException { + byte[] buf = new byte[BUFFER_SIZE]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int n; + while ((n = inputStream.read(buf)) >= 0) { + out.write(buf, 0, n); + } + return out.toByteArray(); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/NetUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/NetUtils.java new file mode 100644 index 00000000..e8d8cce9 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/NetUtils.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ServerSocket; +import java.util.Enumeration; +import java.util.Random; +import java.util.regex.Pattern; + + +/** + * Utiltiy class for net. + * + * @author xiemalin + * @since 2.27 + */ +public class NetUtils { + + /** The Constant logger. */ + private static final Logger LOGGER = LoggerFactory.getLogger(NetUtils.class); + + /** The Constant LOCALHOST. */ + public static final String LOCALHOST = "127.0.0.1"; + + /** The Constant ANYHOST. */ + public static final String ANYHOST = "0.0.0.0"; + + /** The Constant RND_PORT_START. */ + private static final int RND_PORT_START = 30000; + + /** The Constant RND_PORT_RANGE. */ + private static final int RND_PORT_RANGE = 10000; + + /** The Constant RANDOM. */ + private static final Random RANDOM = new Random(System.currentTimeMillis()); + + /** The local address. */ + private static volatile InetAddress LOCAL_ADDRESS = null; + + /** + * Gets the random port. + * + * @return the random port + */ + public static int getRandomPort() { + return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE); + } + + /** + * Gets the available port. + * + * @return the available port + */ + public static int getAvailablePort() { + ServerSocket ss = null; + try { + ss = new ServerSocket(); + ss.bind(null); + return ss.getLocalPort(); + } catch (IOException e) { + return getRandomPort(); + } finally { + if (ss != null) { + try { + ss.close(); + } catch (IOException e) { + } + } + } + } + + /** + * Gets the available port. + * + * @param port the port + * @return the available port + */ + public static int getAvailablePort(int port) { + if (port <= 0) { + return getAvailablePort(); + } + for (int i = port; i < MAX_PORT; i++) { + ServerSocket ss = null; + try { + ss = new ServerSocket(i); + return i; + } catch (IOException e) { + // continue + } finally { + if (ss != null) { + try { + ss.close(); + } catch (IOException e) { + } + } + } + } + return port; + } + + /** The Constant MIN_PORT. */ + private static final int MIN_PORT = 0; + + /** The Constant MAX_PORT. */ + private static final int MAX_PORT = 65535; + + /** + * Checks if is invalid port. + * + * @param port the port + * @return true, if is invalid port + */ + public static boolean isInvalidPort(int port) { + return port > MIN_PORT || port <= MAX_PORT; + } + + /** The Constant ADDRESS_PATTERN. */ + private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); + + /** + * Checks if is valid address. + * + * @param address the address + * @return true, if is valid address + */ + public static boolean isValidAddress(String address) { + return ADDRESS_PATTERN.matcher(address).matches(); + } + + /** The Constant LOCAL_IP_PATTERN. */ + private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); + + /** + * Checks if is local host. + * + * @param host the host + * @return true, if is local host + */ + public static boolean isLocalHost(String host) { + return host != null && (LOCAL_IP_PATTERN.matcher(host).matches() || host.equalsIgnoreCase("localhost")); + } + + /** + * Checks if is any host. + * + * @param host the host + * @return true, if is any host + */ + public static boolean isAnyHost(String host) { + return "0.0.0.0".equals(host); + } + + /** + * Checks if is invalid local host. + * + * @param host the host + * @return true, if is invalid local host + */ + public static boolean isInvalidLocalHost(String host) { + return host == null || host.length() == 0 || host.equalsIgnoreCase("localhost") || host.equals("0.0.0.0") + || (LOCAL_IP_PATTERN.matcher(host).matches()); + } + + /** + * Checks if is valid local host. + * + * @param host the host + * @return true, if is valid local host + */ + public static boolean isValidLocalHost(String host) { + return !isInvalidLocalHost(host); + } + + /** + * Gets the local socket address. + * + * @param host the host + * @param port the port + * @return the local socket address + */ + public static InetSocketAddress getLocalSocketAddress(String host, int port) { + return isInvalidLocalHost(host) ? new InetSocketAddress(port) : new InetSocketAddress(host, port); + } + + /** The Constant IP_PATTERN. */ + private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + + /** + * Checks if is valid address. + * + * @param address the address + * @return true, if is valid address + */ + private static boolean isValidAddress(InetAddress address) { + if (address == null || address.isLoopbackAddress()) + return false; + String name = address.getHostAddress(); + return (name != null && !ANYHOST.equals(name) && !LOCALHOST.equals(name) && IP_PATTERN.matcher(name).matches()); + } + + /** + * Gets the local address. + * + * @return the local address + */ + public static InetAddress getLocalAddress() { + if (LOCAL_ADDRESS != null) + return LOCAL_ADDRESS; + InetAddress localAddress = getLocalAddress0(); + LOCAL_ADDRESS = localAddress; + return localAddress; + } + + /** + * Gets the log host. + * + * @return the log host + */ + public static String getLogHost() { + InetAddress address = LOCAL_ADDRESS; + return address == null ? LOCALHOST : address.getHostAddress(); + } + + /** + * Gets the local address0. + * + * @return the local address0 + */ + private static InetAddress getLocalAddress0() { + InetAddress localAddress = null; + try { + localAddress = InetAddress.getLocalHost(); + if (isValidAddress(localAddress)) { + return localAddress; + } + } catch (Throwable e) { + LOGGER.warn("Failed to retrieve ip address: {}", e); + } + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (interfaces != null) { + while (interfaces.hasMoreElements()) { + try { + NetworkInterface network = interfaces.nextElement(); + Enumeration addresses = network.getInetAddresses(); + if (addresses != null) { + while (addresses.hasMoreElements()) { + try { + InetAddress address = addresses.nextElement(); + if (isValidAddress(address)) { + return address; + } + } catch (Throwable e) { + LOGGER.warn("Failed to retrieve ip address: {}", e); + } + } + } + } catch (Throwable e) { + LOGGER.warn("Failed to retrieve ip address: {}", e); + } + } + } + } catch (Throwable e) { + LOGGER.warn("Failed to retrieve ip address: {}", e); + } + LOGGER.error("Failed to get local host ip address, use 127.0.0.1 instead."); + return localAddress; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/ProtobufUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/ProtobufUtils.java new file mode 100644 index 00000000..e13635fe --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/ProtobufUtils.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import com.baidu.bjf.remoting.protobuf.annotation.Protobuf; +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.google.protobuf.Message; + +import io.netty.buffer.ByteBuf; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProtobufUtils { + public enum MessageType { + PROTOBUF, + JPROTOBUF, + POJO + } + + public static MessageType getMessageType(Method method) { + Class[] types = method.getParameterTypes(); + Class returnType = method.getReturnType(); + if (types.length < 0) { + throw new IllegalArgumentException("invalid rpc method params"); + } + + if (types.length != 1) { + return MessageType.POJO; + } + + Class inputType = types[0]; + if (Message.class.isAssignableFrom(inputType) + && Message.class.isAssignableFrom(returnType)) { + return MessageType.PROTOBUF; + } + + ProtobufClass protobufClass = inputType.getAnnotation(ProtobufClass.class); + if (protobufClass != null) { + return MessageType.JPROTOBUF; + } + + Field[] fields = inputType.getDeclaredFields(); + for (Field field : fields) { + Protobuf protobuf = field.getAnnotation(Protobuf.class); + if (protobuf != null) { + return MessageType.JPROTOBUF; + } + } + + return MessageType.POJO; + } + + public static Message parseFrom(InputStream inputStream, Class clazz) { + try { + Method method = clazz.getMethod("getDefaultInstance"); + Message proto = (Message) method.invoke(null); + proto = proto.newBuilderForType().mergeFrom(inputStream).build(); + return proto; + } catch (Exception ex) { + String errorMsg = String.format("parse proto failed, msg=%s", ex.getMessage()); + log.error(errorMsg); + throw new RuntimeException(errorMsg); + } + } + + public static Message parseFrom(byte[] inputBytes, Class clazz) { + try { + Method method = clazz.getMethod("parseFrom", byte[].class); + Message proto = (Message) method.invoke(null, inputBytes); + return proto; + } catch (Exception ex) { + String errorMsg = String.format("parse proto failed, msg=%s", ex.getMessage()); + log.error(errorMsg); + throw new RuntimeException(errorMsg); + } + } + + /** + * parse proto from netty {@link ByteBuf} + * @param input netty ByteBuf + * @param defaultInstance default instance for proto + * @return proto message + * @throws IOException read io exception + */ + public static Message parseFrom(ByteBuf input, Message defaultInstance) throws IOException { + final int length = input.readableBytes(); + byte[] array = new byte[length]; + input.readBytes(array, 0, length); + return defaultInstance.getParserForType().parseFrom(array); + } + + public static Message parseFrom(byte[] input, Message defaultInstance) throws IOException { + return defaultInstance.getParserForType().parseFrom(input); + } + + public static Message parseFrom(DynamicCompositeByteBuf input, Message defaultInstance) throws IOException { + final byte[] array; + final int offset; + final int length = input.readableBytes(); + array = new byte[length]; + input.readBytes(array, 0, length); + offset = 0; + return defaultInstance.getParserForType().parseFrom(array, offset, length); + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/RpcMetaUtils.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/RpcMetaUtils.java new file mode 100644 index 00000000..023eb974 --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/RpcMetaUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import com.baidu.brpc.protocol.BrpcMeta; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Method; + +@Slf4j +public class RpcMetaUtils { + @Setter + @Getter + public static class RpcMetaInfo { + private String serviceName; + private String methodName; + } + + public static RpcMetaInfo parseRpcMeta(Method targetMethod) { + String serviceName; + String methodName; + BrpcMeta rpcMeta = targetMethod.getAnnotation(BrpcMeta.class); + if (rpcMeta != null) { + serviceName = rpcMeta.serviceName(); + methodName = rpcMeta.methodName(); + } else { + serviceName = targetMethod.getDeclaringClass().getName(); + methodName = targetMethod.getName(); + } + log.debug("serviceName={}, methodName={}", serviceName, methodName); + RpcMetaInfo rpcMetaInfo = new RpcMetaInfo(); + rpcMetaInfo.setServiceName(serviceName); + rpcMetaInfo.setMethodName(methodName); + return rpcMetaInfo; + } +} diff --git a/brpc-java-core/src/main/java/com/baidu/brpc/utils/ThreadPool.java b/brpc-java-core/src/main/java/com/baidu/brpc/utils/ThreadPool.java new file mode 100644 index 00000000..1cb0a1ef --- /dev/null +++ b/brpc-java-core/src/main/java/com/baidu/brpc/utils/ThreadPool.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import java.util.ArrayList; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import lombok.Getter; +import lombok.Setter; + +/** + * Since {@linkplain java.util.concurrent.ExecutorService ExecutorService} is a + * bit slow, we have to invent some wheels here. + *

+ * NOT implement the {@linkplain java.util.concurrent.Executor Executor} + * interface unless we see the necessity + * @author Zhangyi Chen (chenzhangyi01@baidu.com) + * @update Wenwei hu (huwenwei@baidu.com) + */ +public final class ThreadPool { + private static final int DEFAULT_QUEUE_SIZE = 1024; + + // Stand alone lock + private BoundedQueue produced; + private BoundedQueue toConsume; + private Lock consumerLock; + private Lock producerLock; + private Condition isProducerNotFullCondition; + private Condition isProducerNotEmptyCondition; + private ArrayList threads; + + private volatile boolean stopped; + + public ThreadPool(int initialThreadNum, ThreadFactory threadFactory) { + this(initialThreadNum, threadFactory, 0); + } + + public ThreadPool(int initialThreadNum, ThreadFactory threadFactory, int queueSize) { + if (initialThreadNum <= 0) { + throw new IllegalArgumentException( + "initialThreadNum=" + initialThreadNum + + " should be positive" ); + } + threads = new ArrayList(initialThreadNum); + stopped = false; + + if (queueSize <= 0) { + queueSize = DEFAULT_QUEUE_SIZE; + } + produced = new BoundedQueue(queueSize); + toConsume = new BoundedQueue(queueSize); + consumerLock = new ReentrantLock(); + producerLock = new ReentrantLock(); + isProducerNotEmptyCondition = producerLock.newCondition(); + isProducerNotFullCondition = producerLock.newCondition(); + // Start working threads at last, don't put any code after, or there + // will be race condition + for (int i = 0; i < initialThreadNum; ++i) { + Thread tr = threadFactory.newThread(new Runnable() { + @Override + public void run() { + consume(); + } + }); + tr.start(); + threads.add(tr); + } + } + + private void consume() { + while (true) { + Runnable task = null; + while (true) { + consumerLock.lock(); + try { + if (!toConsume.isEmpty()) { + task = toConsume.pop(); + break; + } + } finally { + consumerLock.unlock(); + } + + producerLock.lock(); + try { + while (!stopped && produced.isEmpty()) { + try { + isProducerNotEmptyCondition.await(); + } catch (InterruptedException ex) { + // ignore + } + } + if (!produced.isEmpty()) { + if (produced.isFull()) { + isProducerNotFullCondition.signalAll(); + } + consumerLock.lock(); + try { + BoundedQueue tmp = produced; + produced = toConsume; + toConsume = tmp; + } finally { + consumerLock.unlock(); + } + } else { + // stopped must be true + break; + } + } finally { + producerLock.unlock(); + } + } + if (task != null) { + task.run(); + } else { + // The thread pool was shut down + break; + } + } + } + + public void stop() { + stopped = true; + producerLock.lock(); + try { + isProducerNotEmptyCondition.signalAll(); + isProducerNotFullCondition.signalAll(); + } finally { + producerLock.unlock(); + } + } + + public void join() { + synchronized (threads) { + for (Thread tr : threads) { + try { + tr.join(); + } catch (InterruptedException e) { + // pass + } + } + threads.clear(); + } + } + + public boolean submit(Runnable task) { + Runnable[] tasks = { task }; + return submit(tasks, 0, 1) == 1; + } + + public long submit(Runnable []tasks, int offset, int len) { + int cur = offset; + int end = offset + len; + while (!stopped && cur < end) { + producerLock.lock(); + try { + while (produced.isFull()) { + try { + isProducerNotFullCondition.await(); + } catch (InterruptedException ex) { + // ignore + } + } + int toProduce = Math.min(produced.remainingCapacity(), + end - cur); + if (toProduce > 0) { + boolean wasEmpty = produced.isEmpty(); + produced.addAll(tasks, cur, toProduce); + if (wasEmpty) { + isProducerNotEmptyCondition.signalAll(); + } + } + cur += toProduce; + } finally { + producerLock.unlock(); + } + } + return cur - offset; + } + + public StatInfo getStatInfo() { + StatInfo statInfo = new StatInfo(); + statInfo.setThreadNum(threads.size()); + statInfo.setDefaultQueueCapacity(DEFAULT_QUEUE_SIZE); + statInfo.setProducerQueueSize(produced.size()); + statInfo.setConsumerQueueSize(toConsume.size()); + return statInfo; + } + + @Setter + @Getter + public static class StatInfo { + private int threadNum; + private int defaultQueueCapacity; + private int producerQueueSize; + private int consumerQueueSize; + } + + public boolean isStopped() { + return stopped; + } + +} + diff --git a/brpc-java-core/src/main/proto/baidu_rpc_meta.proto b/brpc-java-core/src/main/proto/baidu_rpc_meta.proto new file mode 100644 index 00000000..cd2d634e --- /dev/null +++ b/brpc-java-core/src/main/proto/baidu_rpc_meta.proto @@ -0,0 +1,38 @@ +syntax="proto2"; +import "options.proto"; +import "streaming_rpc_meta.proto"; + +package brpc.policy; +option java_package="com.baidu.brpc.protocol.standard"; +option java_outer_classname="BaiduRpcProto"; + +message RpcMeta { + optional RpcRequestMeta request = 1; + optional RpcResponseMeta response = 2; + optional int32 compress_type = 3; + optional int64 correlation_id = 4; + optional int32 attachment_size = 5; + optional ChunkInfo chunk_info = 6; + optional bytes authentication_data = 7; + optional StreamSettings stream_settings = 8; +} + +message RpcRequestMetaExtField { + required string key = 1; + required string value = 2; +} + +message RpcRequestMeta { + required string service_name = 1; + required string method_name = 2; + optional int64 log_id = 3; + optional int64 trace_id = 4; + optional int64 span_id = 5; + optional int64 parent_span_id = 6; + repeated RpcRequestMetaExtField ext_fields = 7; +} + +message RpcResponseMeta { + optional int32 error_code = 1; + optional string error_text = 2; +} \ No newline at end of file diff --git a/brpc-java-core/src/main/proto/errno.proto b/brpc-java-core/src/main/proto/errno.proto new file mode 100644 index 00000000..5457309b --- /dev/null +++ b/brpc-java-core/src/main/proto/errno.proto @@ -0,0 +1,166 @@ +syntax="proto2"; +package brpc; +option java_package="com.baidu.brpc.protocol"; +option java_outer_classname="BaiduRpcErrno"; + +enum Errno { + // option allow_alias = false; this option is available since 2.5.0 + // Linux system errno are prefixed with SYS_. + // Since sometimes linux errno such as ENOMEM and ETIMEDOUT is set or + // checked by some other libaries which are out of control by RPC framework, + // it's important to make sure that the explanation of an errno is exactly + // the same in both client-side and server-side. If linux errno is unware + // (e.g. in JAVA program), it's required to use SYS_*. + SYS_EPERM = 1; // Operation not permitted + SYS_ENOENT = 2; // No such file or directory + SYS_ESRCH = 3; // No such process + SYS_EINTR = 4; // Interrupted system call + SYS_EIO = 5; // I/O error + SYS_ENXIO = 6; // No such device or address + SYS_E2BIG = 7; // Arg list too long + SYS_ENOEXEC = 8; // Exec format error + SYS_EBADF = 9; // Bad file number + SYS_ECHILD = 10; // No child processes + SYS_EAGAIN = 11; // Try again + SYS_ENOMEM = 12; // Out of memory + SYS_EACCES = 13; // Permission denied + SYS_EFAULT = 14; // Bad address + SYS_ENOTBLK = 15; // Block device required + SYS_EBUSY = 16; // Device or resource busy + SYS_EEXIST = 17; // File exists + SYS_EXDEV = 18; // Cross-device link + SYS_ENODEV = 19; // No such device + SYS_ENOTDIR = 20; // Not a directory + SYS_EISDIR = 21; // Is a directory + SYS_EINVAL = 22; // Invalid argument + SYS_ENFILE = 23; // File table overflow + SYS_EMFILE = 24; // Too many open files + SYS_ENOTTY = 25; // Not a typewriter + SYS_ETXTBSY = 26; // Text file busy + SYS_EFBIG = 27; // File too large + SYS_ENOSPC = 28; // No space left on device + SYS_ESPIPE = 29; // Illegal seek + SYS_EROFS = 30; // Read-only file system + SYS_EMLINK = 31; // Too many links + SYS_EPIPE = 32; // Broken pipe + SYS_EDOM = 33; // Math argument out of domain of func + SYS_ERANGE = 34; // Math result not representable + SYS_EDEADLK = 35; // Resource deadlock would occur + SYS_ENAMETOOLONG = 36; // File name too long + SYS_ENOLCK = 37; // No record locks available + SYS_ENOSYS = 38; // Function not implemented + SYS_ENOTEMPTY = 39; // Directory not empty + SYS_ELOOP = 40; // Too many symbolic links encountered + SYS_ENOMSG = 42; // No message of desired type + SYS_EIDRM = 43; // Identifier removed + SYS_ECHRNG = 44; // Channel number out of range + SYS_EL2NSYNC = 45; // Level= 2;not synchronized + SYS_EL3HLT = 46; // Level= 3;halted + SYS_EL3RST = 47; // Level= 3;reset + SYS_ELNRNG = 48; // Link number out of range + SYS_EUNATCH = 49; // Protocol driver not attached + SYS_ENOCSI = 50; // No CSI structure available + SYS_EL2HLT = 51; // Level= 2;halted + SYS_EBADE = 52; // Invalid exchange + SYS_EBADR = 53; // Invalid request descriptor + SYS_EXFULL = 54; // Exchange full + SYS_ENOANO = 55; // No anode + SYS_EBADRQC = 56; // Invalid request code + SYS_EBADSLT = 57; // Invalid slot + SYS_EBFONT = 59; // Bad font file format + SYS_ENOSTR = 60; // Device not a stream + SYS_ENODATA = 61; // No data available + SYS_ETIME = 62; // Timer expired + SYS_ENOSR = 63; // Out of streams resources + SYS_ENONET = 64; // Machine is not on the network + SYS_ENOPKG = 65; // Package not installed + SYS_EREMOTE = 66; // Object is remote + SYS_ENOLINK = 67; // Link has been severed + SYS_EADV = 68; // Advertise error + SYS_ESRMNT = 69; // Srmount error + SYS_ECOMM = 70; // Communication error on send + SYS_EPROTO = 71; // Protocol error + SYS_EMULTIHOP = 72; // Multihop attempted + SYS_EDOTDOT = 73; // RFS specific error + SYS_EBADMSG = 74; // Not a data message + SYS_EOVERFLOW = 75; // Value too large for defined data type + SYS_ENOTUNIQ = 76; // Name not unique on network + SYS_EBADFD = 77; // File descriptor in bad state + SYS_EREMCHG = 78; // Remote address changed + SYS_ELIBACC = 79; // Can not access a needed shared library + SYS_ELIBBAD = 80; // Accessing a corrupted shared library + SYS_ELIBSCN = 81; // .lib section in a.out corrupted + SYS_ELIBMAX = 82; // Attempting to link in too many shared libraries + SYS_ELIBEXEC = 83; // Cannot exec a shared library directly + SYS_EILSEQ = 84; // Illegal byte sequence + SYS_ERESTART = 85; // Interrupted system call should be restarted + SYS_ESTRPIPE = 86; // Streams pipe error + SYS_EUSERS = 87; // Too many users + SYS_ENOTSOCK = 88; // Socket operation on non-socket + SYS_EDESTADDRREQ = 89; // Destination address required + SYS_EMSGSIZE = 90; // Message too long + SYS_EPROTOTYPE = 91; // Protocol wrong type for socket + SYS_ENOPROTOOPT = 92; // Protocol not available + SYS_EPROTONOSUPPORT = 93; // Protocol not supported + SYS_ESOCKTNOSUPPORT = 94; // Socket type not supported + SYS_EOPNOTSUPP = 95; // Operation not supported on transport endpoint + SYS_EPFNOSUPPORT = 96; // Protocol family not supported + SYS_EAFNOSUPPORT = 97; // Address family not supported by protocol + SYS_EADDRINUSE = 98; // Address already in use + SYS_EADDRNOTAVAIL = 99; // Cannot assign requested address + SYS_ENETDOWN = 100; // Network is down + SYS_ENETUNREACH = 101; // Network is unreachable + SYS_ENETRESET = 102; // Network dropped connection because of reset + SYS_ECONNABORTED = 103; // Software caused connection abort + SYS_ECONNRESET = 104; // Connection reset by peer + SYS_ENOBUFS = 105; // No buffer space available + SYS_EISCONN = 106; // Transport endpoint is already connected + SYS_ENOTCONN = 107; // Transport endpoint is not connected + SYS_ESHUTDOWN = 108; // Cannot send after transport endpoint shutdown + SYS_ETOOMANYREFS = 109; // Too many references: cannot splice + SYS_ETIMEDOUT = 110; // Connection timed out. NOTE: RPC timeout is ERPCTIMEDOUT. + SYS_ECONNREFUSED = 111; // Connection refused + SYS_EHOSTDOWN = 112; // Host is down + SYS_EHOSTUNREACH = 113; // No route to host + SYS_EALREADY = 114; // Operation already in progress + SYS_EINPROGRESS = 115; // Operation now in progress + SYS_ESTALE = 116; // Stale NFS file handle + SYS_EUCLEAN = 117; // Structure needs cleaning + SYS_ENOTNAM = 118; // Not a XENIX named type file + SYS_ENAVAIL = 119; // No XENIX semaphores available + SYS_EISNAM = 120; // Is a named type file + SYS_EREMOTEIO = 121; // Remote I/O error + SYS_EDQUOT = 122; // Quota exceeded + SYS_ENOMEDIUM = 123; // No medium found + SYS_EMEDIUMTYPE = 124; // Wrong medium type + SYS_ECANCELED = 125; // Operation Cancelled + SYS_ENOKEY = 126; // Required key not available + SYS_EKEYEXPIRED = 127; // Key has expired + SYS_EKEYREVOKED = 128; // Key has been revoked + SYS_EKEYREJECTED = 129; // Key was rejected by service + + // Errno caused by client + ENOSERVICE = 1001; // Service not found + ENOMETHOD = 1002; // Method not found + EREQUEST = 1003; // Bad Request + EAUTH = 1004; // Unauthorized + ETOOMANYFAILS = 1005; // Too many sub calls failed + EPCHANFINISH = 1006; // [Internal] ParallelChannel finished + EBACKUPREQUEST = 1007; // Sending backup request + ERPCTIMEDOUT = 1008; // RPC call is timed out + EFAILEDSOCKET = 1009; // Broken socket + EHTTP = 1010; // Bad http call + EOVERCROWDED = 1011; // The server is overcrowded + ERTMPPUBLISHABLE = 1012; // RtmpRetryingClientStream is publishable + ERTMPCREATESTREAM = 1013; // createStream was rejected by the RTMP server + EEOF = 1014; // Got EOF + EUNUSED = 1015; // The socket was not needed + + // Errno caused by server + EINTERNAL = 2001; // Internal Server Error + ERESPONSE = 2002; // Bad Response + ELOGOFF = 2003; // Server is stopping + ELIMIT = 2004; // Reached server's limit on resources + ECLOSE = 2005; // Close socket initiatively + EITP = 2006; // Failed Itp response +} diff --git a/brpc-java-core/src/main/proto/hulu_pbrpc_meta.proto b/brpc-java-core/src/main/proto/hulu_pbrpc_meta.proto new file mode 100644 index 00000000..073436fd --- /dev/null +++ b/brpc-java-core/src/main/proto/hulu_pbrpc_meta.proto @@ -0,0 +1,53 @@ +syntax="proto2"; +import "options.proto"; // For TalkType + +package brpc.policy; +option java_package="com.baidu.brpc.protocol.hulu"; +option java_outer_classname="HuluRpcProto"; + +enum HuluCompressType { + HULU_COMPRESS_TYPE_NONE = 0; + HULU_COMPRESS_TYPE_SNAPPY = 1; + HULU_COMPRESS_TYPE_GZIP = 2; + HULU_COMPRESS_TYPE_ZLIB = 3; +} + +message HuluRpcRequestMetaExtField { + required string key = 1; + required string value = 2; +} + +message HuluRpcRequestMeta { + required string service_name = 1; + required int32 method_index = 2; + optional int32 compress_type = 3; + optional int64 correlation_id = 4; + optional int64 log_id = 5; + optional ChunkInfo chuck_info = 6; + + optional int64 trace_id = 7; + optional int64 parent_span_id = 8; + optional int64 span_id = 9; + + optional TalkType request_talk_type = 10; + optional bytes user_data = 11; + + optional int32 user_message_size = 12; + optional int64 user_defined_source_addr = 13; + optional string method_name = 14; + optional bytes credential_data = 15; + + repeated HuluRpcRequestMetaExtField ext_fields = 16; +} + +message HuluRpcResponseMeta { + optional int32 error_code = 1; + optional string error_text = 2; + optional sint64 correlation_id = 3; + optional int32 compress_type = 4; + optional ChunkInfo chuck_info = 5; + optional TalkType response_talk_type = 6; + optional bytes user_data = 7; + optional int32 user_message_size = 8; + optional int64 user_defined_source_addr = 9; +} diff --git a/brpc-java-core/src/main/proto/options.proto b/brpc-java-core/src/main/proto/options.proto new file mode 100644 index 00000000..c090b44a --- /dev/null +++ b/brpc-java-core/src/main/proto/options.proto @@ -0,0 +1,88 @@ +syntax="proto2"; +import "google/protobuf/descriptor.proto"; + +package brpc; +option java_package="com.baidu.brpc.protocol"; +option java_outer_classname="Options"; + +enum TalkType { + TALK_TYPE_NORMAL = 0; + TALK_TYPE_ONEWAY = 1; +} + +enum ConnectionType { + // bit-exclusive values since we may OR them to represent supported types. + CONNECTION_TYPE_UNKNOWN = 0; + CONNECTION_TYPE_SINGLE = 1; + CONNECTION_TYPE_POOLED = 2; + CONNECTION_TYPE_SHORT = 4; +} + +enum ProtocolType { + PROTOCOL_UNKNOWN = 0; + PROTOCOL_BAIDU_STD = 1; + PROTOCOL_STREAMING_RPC = 2; + PROTOCOL_HULU_PBRPC = 3; + PROTOCOL_SOFA_PBRPC = 4; + PROTOCOL_RTMP = 5; + PROTOCOL_HTTP = 6; + PROTOCOL_PUBLIC_PBRPC = 7; + PROTOCOL_NOVA_PBRPC = 8; + PROTOCOL_NSHEAD_CLIENT = 9; // implemented in baidu-rpc-ub + PROTOCOL_NSHEAD = 10; + PROTOCOL_HADOOP_RPC = 11; + PROTOCOL_HADOOP_SERVER_RPC = 12; + PROTOCOL_MONGO = 13; // server side only + PROTOCOL_UBRPC_COMPACK = 14; + PROTOCOL_DIDX_CLIENT = 15; // Client side only + PROTOCOL_REDIS = 16; // Client side only + PROTOCOL_MEMCACHE = 17; // Client side only + PROTOCOL_ITP = 18; + PROTOCOL_NSHEAD_MCPACK = 19; + PROTOCOL_DISP_IDL = 20; // Client side only + PROTOCOL_ERSDA_CLIENT = 21; // Client side only + PROTOCOL_UBRPC_MCPACK2 = 22; // Client side only + // Reserve special protocol for cds-agent, which depends on FIFO right now + PROTOCOL_CDS_AGENT = 23; // Client side only + PROTOCOL_ESP = 24; // Client side only + PROTOCOL_BAIDU_JSON_RPC_MCPACK = 25; // baidu http json rpc: http + mcpack + PROTOCOL_BAIDU_JSON_RPC_JSON = 26; // baidu http json rpc: http + json + PROTOCOL_NSHEAD_PROTOBUF = 28; // nshead + protobuf + PROTOCOL_HTTP_PROTOBUF = 29; // http + protobuf + PROTOCOL_HTTP_JSON = 30; // http + json + PROTOCOL_NSHEAD_JSON = 31; // nshead + json + PROTOCOL_STARGATE = 32; // Stargate + PROTOCOL_SERVER_PUSH = 33; // default server push protocol + +} + +enum CompressType { + COMPRESS_TYPE_NONE = 0; + COMPRESS_TYPE_SNAPPY = 1; + COMPRESS_TYPE_GZIP = 2; + COMPRESS_TYPE_ZLIB = 3; + COMPRESS_TYPE_LZ4 = 4; +} + +message ChunkInfo { + required int64 stream_id = 1; + required int64 chunk_id = 2; +} + +extend google.protobuf.ServiceOptions { + // Timeout in milliseconds, at service level. + optional int64 service_timeout = 90000 [default = 10000]; +} + +extend google.protobuf.MethodOptions { + // Talk type. + optional TalkType request_talk_type = 90001 [default = TALK_TYPE_NORMAL]; + optional TalkType response_talk_type = 90002 [default = TALK_TYPE_NORMAL]; + + // If set, override service_timeout. + optional int64 method_timeout = 90003; + + // Compression for request/response. + optional CompressType request_compression = 90004 [default = COMPRESS_TYPE_NONE]; + optional CompressType response_compression = 90005 [default = COMPRESS_TYPE_NONE]; +} diff --git a/brpc-java-core/src/main/proto/public_pbrpc_meta.proto b/brpc-java-core/src/main/proto/public_pbrpc_meta.proto new file mode 100644 index 00000000..f1d688df --- /dev/null +++ b/brpc-java-core/src/main/proto/public_pbrpc_meta.proto @@ -0,0 +1,44 @@ +syntax="proto2"; + +package brpc.policy; +option java_package = "com.baidu.brpc.protocol.pbrpc"; +option java_outer_classname = "PublicPbrpcProto"; + +message PublicPbrpcRequest{ + optional RequestHead requestHead = 1; + repeated RequestBody requestBody = 2; +} +message RequestHead{ + optional string from_host = 1; + optional uint32 content_type = 2; + optional bool connection = 3; + optional string charset = 4; + optional string accept_charset = 5; + optional string create_time = 6; + optional uint64 log_id = 7; + optional uint32 compress_type = 8; +} +message RequestBody{ + optional string version = 1; + optional string charset = 2; + required string service = 3; + required uint32 method_id = 4; + required uint64 id = 5; + optional bytes serialized_request = 6; +} +message PublicPbrpcResponse { + optional ResponseHead responseHead = 1; + repeated ResponseBody responseBody = 2; +} +message ResponseHead{ + required sint32 code = 1; + optional string text = 2; + optional string from_host = 3; + optional uint32 compress_type = 4; +} +message ResponseBody{ + optional bytes serialized_response = 1; + optional string version = 2; + optional int32 error = 3; + required uint64 id = 4; +} diff --git a/brpc-java-core/src/main/proto/sofa_pbrpc_meta.proto b/brpc-java-core/src/main/proto/sofa_pbrpc_meta.proto new file mode 100644 index 00000000..6c87e5de --- /dev/null +++ b/brpc-java-core/src/main/proto/sofa_pbrpc_meta.proto @@ -0,0 +1,58 @@ +syntax="proto2"; +// Meta of sofa-pbrpc https://github.com/baidu/sofa-pbrpc + +package brpc.policy; +option java_package = "com.baidu.brpc.protocol.sofa"; +option java_outer_classname = "SofaRpcProto"; + +enum SofaCompressType { + SOFA_COMPRESS_TYPE_NONE = 0; + SOFA_COMPRESS_TYPE_GZIP = 1; + SOFA_COMPRESS_TYPE_ZLIB = 2; + SOFA_COMPRESS_TYPE_SNAPPY = 3; + SOFA_COMPRESS_TYPE_LZ4 = 4; +} + +message SofaRpcMeta { + + ///////////////////////////////////////////////////// + // The following fields are used both for request and response. + + // Message type. + enum Type { + REQUEST = 0; + RESPONSE = 1; + }; + required Type type = 1; + + // Message sequence id. + required uint64 sequence_id = 2; + + ///////////////////////////////////////////////////// + // The following fields are used only for request. + + // Method full name. + // For io.brpc.example.example: "test.HelloService.GreetMethod" + optional string method = 100; + + ///////////////////////////////////////////////////// + // The following fields are used only for response. + + // Set as true if the call is failed. + optional bool failed = 200; + + // The error code if the call is failed. + optional int32 error_code = 201; + + // The error reason if the call is failed. + optional string reason = 202; + + ///////////////////////////////////////////////////// + // Compression related fields. + + // Set the request/response compress type. + optional SofaCompressType compress_type = 300; + + // Set the response compress type of user expected. + optional SofaCompressType expected_response_compress_type = 301; +} diff --git a/brpc-java-core/src/main/proto/streaming_rpc_meta.proto b/brpc-java-core/src/main/proto/streaming_rpc_meta.proto new file mode 100644 index 00000000..4a9351e2 --- /dev/null +++ b/brpc-java-core/src/main/proto/streaming_rpc_meta.proto @@ -0,0 +1,32 @@ +syntax="proto2"; +import "options.proto"; + +package brpc; +option java_package="com.baidu.brpc.protocol"; +option java_outer_classname="StreamingRpcProto"; + +message StreamSettings { + required int64 stream_id = 1; + optional bool need_feedback = 2 [default = false]; + optional bool writable = 3 [default = false]; +} + +enum FrameType { + FRAME_TYPE_UNKNOWN = 0; + FRAME_TYPE_RST = 1; + FRAME_TYPE_CLOSE = 2; + FRAME_TYPE_DATA = 3; + FRAME_TYPE_FEEDBACK= 4; +} + +message StreamFrameMeta { + required int64 stream_id = 1; + optional int64 source_stream_id = 2; + optional FrameType frame_type = 3; + optional bool has_continuation = 4; + optional Feedback feedback = 5; +} + +message Feedback { + optional int64 consumed_size = 1; +} diff --git a/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.client.loadbalance.LoadBalanceFactory b/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.client.loadbalance.LoadBalanceFactory new file mode 100644 index 00000000..6dcd4b36 --- /dev/null +++ b/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.client.loadbalance.LoadBalanceFactory @@ -0,0 +1,4 @@ +com.baidu.brpc.client.loadbalance.RandomLoadBalanceFactory +com.baidu.brpc.client.loadbalance.RoundRobinLoadBalanceFactory +com.baidu.brpc.client.loadbalance.WeightLoadBalanceFactory +com.baidu.brpc.client.loadbalance.FairLoadBalanceFactory \ No newline at end of file diff --git a/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.protocol.ProtocolFactory b/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.protocol.ProtocolFactory new file mode 100644 index 00000000..b5098aff --- /dev/null +++ b/brpc-java-core/src/main/resources/META-INF/services/com.baidu.brpc.protocol.ProtocolFactory @@ -0,0 +1,9 @@ +com.baidu.brpc.protocol.standard.BaiduRpcProtocolFactory +com.baidu.brpc.protocol.sofa.SofaRpcProtocolFactory +com.baidu.brpc.protocol.hulu.HuluRpcProtocolFactory +com.baidu.brpc.protocol.nshead.NSHeadJsonProtocolFactory +com.baidu.brpc.protocol.nshead.NSHeadProtobufProtocolFactory +com.baidu.brpc.protocol.stargate.StargateRpcProtocolFactory +com.baidu.brpc.protocol.http.HttpProtobufProtocolFactory +com.baidu.brpc.protocol.http.HttpJsonProtocolFactory +com.baidu.brpc.protocol.push.ServerPushProtocolFactory \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/RpcMethodInfoTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/RpcMethodInfoTest.java new file mode 100644 index 00000000..a6b66653 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/RpcMethodInfoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Method; + +public class RpcMethodInfoTest { + @Test + public void testRpcMethodInfo() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + RpcMethodInfo rpcMethodInfo = new RpcMethodInfo(method); + Assert.assertTrue(rpcMethodInfo != null); + Assert.assertTrue(rpcMethodInfo.getMethodName().equals("Echo")); + Assert.assertTrue(rpcMethodInfo.getServiceName().equals("example.EchoService")); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/RpcOptionsUtils.java b/brpc-java-core/src/test/java/com/baidu/brpc/RpcOptionsUtils.java new file mode 100644 index 00000000..4f072044 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/RpcOptionsUtils.java @@ -0,0 +1,21 @@ +package com.baidu.brpc; + +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.server.RpcServerOptions; + +public class RpcOptionsUtils { + public static RpcClientOptions getRpcClientOptions() { + RpcClientOptions options = new RpcClientOptions(); + options.setIoThreadNum(1); + options.setWorkThreadNum(1); + options.setMinIdleConnections(1); + return options; + } + + public static RpcServerOptions getRpcServerOptions() { + RpcServerOptions options = new RpcServerOptions(); + options.setIoThreadNum(1); + options.setWorkThreadNum(1); + return options; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/TestJprotobufRpcMethodInfo.java b/brpc-java-core/src/test/java/com/baidu/brpc/TestJprotobufRpcMethodInfo.java new file mode 100644 index 00000000..4e5506e3 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/TestJprotobufRpcMethodInfo.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.jprotobuf.EchoResponse; +import com.baidu.brpc.protocol.jprotobuf.EchoService; +import com.baidu.brpc.protocol.standard.Echo; +import com.google.protobuf.CodedOutputStream; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import org.junit.Assert; +import org.junit.Test; + +import java.io.OutputStream; +import java.lang.reflect.Method; + +public class TestJprotobufRpcMethodInfo { + @Test + public void testProtobufRpcMethodInfo() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + Assert.assertTrue(rpcMethodInfo.getInputCodec() != null); + Assert.assertTrue(rpcMethodInfo.getOutputCodec() != null); + } + + @Test + public void testInputEncode() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + + + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + byte[] bytes = rpcMethodInfo.inputEncode(request); + Assert.assertTrue(bytes != null); + Assert.assertTrue(bytes.length + == Echo.EchoRequest.newBuilder().setMessage("hello").build().getSerializedSize()); + } + + @Test + public void testInputWriteToStream() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf buf = Unpooled.buffer(64); + OutputStream outputStream = new ByteBufOutputStream(buf); + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream); + rpcMethodInfo.inputWriteToStream(request, codedOutputStream); + Assert.assertTrue(buf.readableBytes() + == Echo.EchoRequest.newBuilder().setMessage("hello").build().getSerializedSize()); + } + + @Test + public void testOutputDecodeBytes() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + EchoResponse response1 = (EchoResponse) rpcMethodInfo.outputDecode(bytes); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testOutputDecodeByteBuf() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + EchoResponse response1 = (EchoResponse) rpcMethodInfo.outputDecode(buf); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testOutputDecodeDynamicCompositeByteBuf() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + EchoResponse response1 = (EchoResponse) rpcMethodInfo.outputDecode(compositeByteBuf); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testInputDecode() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + EchoRequest request1 = (EchoRequest) rpcMethodInfo.inputDecode(bytes); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testInputDecode2() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); + EchoRequest request1 = (EchoRequest) rpcMethodInfo.inputDecode(byteBuf); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testInputDecode3() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(byteBuf); + EchoRequest request1 = (EchoRequest) rpcMethodInfo.inputDecode(compositeByteBuf); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testOutputEncode() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + byte[] bytes = rpcMethodInfo.outputEncode(response); + Assert.assertTrue(bytes.length + == Echo.EchoResponse.newBuilder().setMessage("hello").build().toByteArray().length); + } + + @Test + public void testGetInputSerializedSize() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + Assert.assertTrue(rpcMethodInfo.getInputSerializedSize(request) + == Echo.EchoRequest.newBuilder().setMessage("hello").build().getSerializedSize()); + } + + @Test + public void testGetOutputSerializedSize() throws Exception { + Method method = EchoService.class.getMethod("echo", EchoRequest.class); + JprotobufRpcMethodInfo rpcMethodInfo = new JprotobufRpcMethodInfo(method); + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + Assert.assertTrue(rpcMethodInfo.getOutputSerializedSize(response) + == Echo.EchoResponse.newBuilder().setMessage("hello").build().getSerializedSize()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/TestProtobufRpcMethodInfo.java b/brpc-java-core/src/test/java/com/baidu/brpc/TestProtobufRpcMethodInfo.java new file mode 100644 index 00000000..30ef2a53 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/TestProtobufRpcMethodInfo.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc; + +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.google.protobuf.CodedOutputStream; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import org.junit.Assert; +import org.junit.Test; + +import java.io.OutputStream; +import java.lang.reflect.Method; + +public class TestProtobufRpcMethodInfo { + @Test + public void testProtobufRpcMethodInfo() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Assert.assertTrue(rpcMethodInfo.getInputInstance() != null); + Assert.assertTrue(rpcMethodInfo.getInputGetDefaultInstanceMethod() != null); + } + + @Test + public void testInputEncode() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = rpcMethodInfo.inputEncode(request); + Assert.assertTrue(bytes != null); + Assert.assertTrue(bytes.length == request.getSerializedSize()); + } + + @Test + public void testInputWriteToStream() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf buf = Unpooled.buffer(request.getSerializedSize()); + OutputStream outputStream = new ByteBufOutputStream(buf); + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream); + rpcMethodInfo.inputWriteToStream(request, codedOutputStream); + Assert.assertTrue(buf.readableBytes() == request.getSerializedSize()); + } + + @Test + public void testOutputDecodeBytes() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + Echo.EchoResponse response1 = (Echo.EchoResponse) rpcMethodInfo.outputDecode(bytes); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testOutputDecodeByteBuf() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + Echo.EchoResponse response1 = (Echo.EchoResponse) rpcMethodInfo.outputDecode(buf); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testOutputDecodeDynamicCompositeByteBuf() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + Echo.EchoResponse response1 = (Echo.EchoResponse) rpcMethodInfo.outputDecode(compositeByteBuf); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testOutputDecodeStream() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = response.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + ByteBufInputStream inputStream = new ByteBufInputStream(buf); + Echo.EchoResponse response1 = (Echo.EchoResponse) rpcMethodInfo.outputDecode(inputStream); + Assert.assertTrue(response1.getMessage().equals(response.getMessage())); + } + + @Test + public void testInputDecode() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + Echo.EchoRequest request1 = (Echo.EchoRequest) rpcMethodInfo.inputDecode(bytes); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testInputDecode2() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + Echo.EchoRequest request1 = (Echo.EchoRequest) rpcMethodInfo.inputDecode(bytes, 0, bytes.length); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testInputDecode3() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); + Echo.EchoRequest request1 = (Echo.EchoRequest) rpcMethodInfo.inputDecode(byteBuf); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testInputDecode4() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(byteBuf); + Echo.EchoRequest request1 = (Echo.EchoRequest) rpcMethodInfo.inputDecode(compositeByteBuf); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testOutputEncode() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + byte[] bytes = rpcMethodInfo.outputEncode(response); + Assert.assertTrue(bytes.length == response.toByteArray().length); + } + + @Test + public void testGetInputSerializedSize() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Assert.assertTrue(rpcMethodInfo.getInputSerializedSize(request) == request.getSerializedSize()); + } + + @Test + public void testGetOutputSerializedSize() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufRpcMethodInfo rpcMethodInfo = new ProtobufRpcMethodInfo(method); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + Assert.assertTrue(rpcMethodInfo.getOutputSerializedSize(response) == response.getSerializedSize()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/buffer/ByteBufTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/ByteBufTest.java new file mode 100644 index 00000000..15ff4929 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/ByteBufTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.Test; + +public class ByteBufTest { + + @Test + public void testSlice() { + byte[] bytes = new byte[10]; + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + ByteBuf buf2 = buf.slice(0, 2); + System.out.println(buf.refCnt()); + System.out.println(buf2.refCnt()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStreamTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStreamTest.java new file mode 100644 index 00000000..a7ce354c --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufInputStreamTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class DynamicCompositeByteBufInputStreamTest { + @Test + public void testRead() throws IOException { + ByteBuf buf = Unpooled.buffer(12); + buf.writeByte(1); + buf.writeByte(2); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + DynamicCompositeByteBufInputStream inputStream = new DynamicCompositeByteBufInputStream(compositeByteBuf); + Assert.assertTrue(inputStream != null); + int b = inputStream.read(); + Assert.assertTrue(b == 1); + + Assert.assertTrue(buf.refCnt() == 1); + inputStream.close(); + Assert.assertTrue(buf.refCnt() == 1); + compositeByteBuf.release(); + Assert.assertTrue(buf.refCnt() == 0); + inputStream.close(); + } + + @Test + public void testReadBytes() throws IOException { + byte[] bytes = "hello".getBytes(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + DynamicCompositeByteBufInputStream inputStream = new DynamicCompositeByteBufInputStream(compositeByteBuf); + + byte[] dstBytes = new byte[bytes.length]; + inputStream.read(dstBytes, 0, bytes.length); + for (int i = 0; i < bytes.length; i++) { + Assert.assertTrue(dstBytes[i] == bytes[i]); + } + compositeByteBuf.release(); + inputStream.close(); + } + + @Test + public void testSkip() throws IOException { + ByteBuf buf = Unpooled.buffer(12); + buf.writeInt(12); + buf.writeInt(23); + buf.writeInt(34); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + DynamicCompositeByteBufInputStream inputStream = new DynamicCompositeByteBufInputStream(compositeByteBuf); + inputStream.skip(4); + int i = inputStream.readInt(); + Assert.assertTrue(i == 23); + compositeByteBuf.release(); + inputStream.close(); + } +} diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/buffer/DynamicCompositeByteBufTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufTest.java similarity index 97% rename from starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/buffer/DynamicCompositeByteBufTest.java rename to brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufTest.java index 47d73d45..f2c93aa1 100644 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/buffer/DynamicCompositeByteBufTest.java +++ b/brpc-java-core/src/test/java/com/baidu/brpc/buffer/DynamicCompositeByteBufTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.baidu.cloud.starlight.transport.buffer; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; +package com.baidu.brpc.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import org.junit.Assert; import org.junit.Test; -/** - * Created by liuruisen on 2020/3/20. - */ public class DynamicCompositeByteBufTest { - @Test public void testDynamicCompositeByteBuf() { DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); @@ -306,5 +301,4 @@ public void testRelease() { Assert.assertTrue(buf1.refCnt() == 0); Assert.assertTrue(buf2.refCnt() == 0); } - -} \ No newline at end of file +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelGroupTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelGroupTest.java new file mode 100644 index 00000000..0df981a7 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelGroupTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Queue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.BrpcPooledChannel; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; + +import io.netty.channel.Channel; + +public class BrpcChannelGroupTest { + + private RpcServer rpcServer; + + private RpcClient rpcClient; + + private BrpcChannel channelGroup; + + private RpcClientOptions options; + + @Before + public void before() { + rpcServer = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.start(); + options = RpcOptionsUtils.getRpcClientOptions(); + options.setLatencyWindowSizeOfFairLoadBalance(2); + rpcClient = new RpcClient("list://127.0.0.1:8000", options); + channelGroup = new BrpcPooledChannel(new ServiceInstance("127.0.0.1", 8000), rpcClient); + } + + @After + public void after() { + if (rpcClient != null) { + rpcClient.stop(); + } + if (rpcServer != null) { + rpcServer.shutdown(); + } + } + + @Test + public void test() throws Exception { + Channel channel = channelGroup.getChannel(); + assertThat(channel.isActive(), is(true)); + channelGroup.returnChannel(channel); + channel = channelGroup.connect("127.0.0.1", 8000); + assertThat(channel.isActive(), is(true)); + channel.close(); + channelGroup.updateLatency(10); + channelGroup.updateLatencyWithReadTimeOut(); + Queue latencyWindow = channelGroup.getLatencyWindow(); + assertThat(latencyWindow.poll(), is(10)); + assertThat(latencyWindow.poll(), is(options.getReadTimeoutMillis())); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelTest.java new file mode 100644 index 00000000..b094a1bd --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/BrpcChannelTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Queue; + +import com.baidu.brpc.server.RpcServerOptions; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.BrpcPooledChannel; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; + +import io.netty.channel.Channel; + +public class BrpcChannelTest { + + private RpcServer rpcServer; + + private RpcClient rpcClient; + + private BrpcChannel channelGroup; + + private RpcClientOptions options; + + @Before + public void before() { + rpcServer = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.start(); + options = RpcOptionsUtils.getRpcClientOptions(); + options.setLatencyWindowSizeOfFairLoadBalance(2); + rpcClient = new RpcClient("list://127.0.0.1:8000", options); + channelGroup = new BrpcPooledChannel(new ServiceInstance("127.0.0.1", 8000), rpcClient); + } + + @After + public void after() { + if (rpcClient != null) { + rpcClient.shutdown(); + } + if (rpcServer != null) { + rpcServer.shutdown(); + } + } + + @Test + public void test() throws Exception { + Channel channel = channelGroup.getChannel(); + assertThat(channel.isActive(), is(true)); + channelGroup.returnChannel(channel); + channel = channelGroup.connect("127.0.0.1", 8000); + assertThat(channel.isActive(), is(true)); + channel.close(); + channelGroup.updateLatency(10); + channelGroup.updateLatencyWithReadTimeOut(); + Queue latencyWindow = channelGroup.getLatencyWindow(); + assertThat(latencyWindow.poll(), is(10)); + assertThat(latencyWindow.poll(), is(options.getReadTimeoutMillis())); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/ClientInitTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/ClientInitTest.java new file mode 100644 index 00000000..69e379bb --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/ClientInitTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import com.baidu.brpc.client.instance.Endpoint; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ClientInitTest { + + @Test + public void testClientInit() { + + RpcServer rpcServer = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // new first rpc client + long firstStartTime = System.currentTimeMillis(); + RpcClient firstRpcClient = new RpcClient("list://127.0.0.1:8000", + RpcOptionsUtils.getRpcClientOptions()); + long firstEndTime = System.currentTimeMillis(); + + EchoService echoService = BrpcProxy.getProxy(firstRpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + log.info("first new rpcClient cost : {}", firstEndTime - firstStartTime); + + // new second rpc client + long secondStartTime = System.currentTimeMillis(); + RpcClient secondRpcClient = new RpcClient("list://127.0.0.1:8000", + RpcOptionsUtils.getRpcClientOptions()); + long secondEndTime = System.currentTimeMillis(); + log.info("second new rpcClient cost : {}", secondEndTime - secondStartTime); + echoService = BrpcProxy.getProxy(secondRpcClient, EchoService.class); + request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + + // new third rpc client for short connection + Endpoint endPoint = new Endpoint("127.0.0.1", 8000); + long thirdStartTime = System.currentTimeMillis(); + RpcClient thirdConnectionRpcClient = new RpcClient(endPoint, + RpcOptionsUtils.getRpcClientOptions()); + long thirdEndTime = System.currentTimeMillis(); + log.info("third new rpcClient cost : {}", thirdEndTime - thirdStartTime); + + ThreadNumStat stat = calThreadNum(); + Assert.assertEquals(3, stat.workThreadNum); + Assert.assertEquals(1, stat.timoutThreadNum); + + firstRpcClient.stop(); + secondRpcClient.stop(); + thirdConnectionRpcClient.stop(); + rpcServer.shutdown(); + } + + + private ThreadNumStat calThreadNum() { + ThreadNumStat stat = new ThreadNumStat(); + + // stat all thread + Map allThreadMap = Thread.getAllStackTraces(); + for (Map.Entry entry : allThreadMap.entrySet()) { + + Thread thread = entry.getKey(); + + if (thread.getName().contains("invalid-channel-callback-thread")) { + stat.callBackThreadNum ++; + } else if (thread.getName().contains("client-io-thread")) { + stat.ioThreadNum ++; + } else if (thread.getName().contains("client-work-thread")) { + stat.workThreadNum ++; + } else if (thread.getName().contains("health-check-timer-thread")) { + stat.healthCheckThreadNum ++; + } else if (thread.getName().contains("timeout-timer-thread")) { + stat.timoutThreadNum ++; + } + } + + log.info("thread statistic data, callBackThreadNum : {}, \n ioThreadNum : {}, \n workThreadNum : {}, \n" + + " healthCheckThreadNum : {}, \n timeoutThreadNum : {} \n", stat.callBackThreadNum, + stat.ioThreadNum, stat.workThreadNum, stat.healthCheckThreadNum, stat.timoutThreadNum); + + return stat; + } + + + public static class ThreadNumStat { + public int callBackThreadNum; + public int ioThreadNum; + public int workThreadNum; + public int healthCheckThreadNum; + public int timoutThreadNum; + } + + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreBenchmark.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreBenchmark.java new file mode 100644 index 00000000..a7b31dad --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreBenchmark.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * benchmark + * + * Created by wanghongfei on 2018/11/19. + */ +public class FastFutureStoreBenchmark { + @Test + public void testBenchmark() throws Exception { + // int times = 200000; + // int times = 1500000; + int times = 3000000; + // int times = 6000000; + + // warm jvm + runMap(times, 1); + runStore(times, 1); + runMap(times, 1); + runStore(times, 1); + + System.out.println("warm done"); + + List all = new ArrayList(); + for (int ix = 0 ; ix < 50; ++ix) { + long t1 = runStore(times, 4); + + long t2 = runMap(times, 4); + + System.out.println("diff = " + (t2 - t1) + ", " + ((double) t2) / t1); + + double ratio = ((double) t2 / t1); + all.add(ratio); + } + + double sum = 0; + for (Double n : all) { + sum += n; + } + + double result = sum / all.size(); + System.out.println(); + System.out.println(result); + + // Runtime.getRuntime().exec("say -v Ting-ting benchmark完成了, 结果是 " + result); + } + + /** + * 运行FastFutureStore benchmark + * + * @param count 最大id数量 + * @param threadCount 并发线程数 + * @return + * @throws Exception + */ + private long runStore(final int count, final int threadCount) throws Exception { + final AtomicLong result = new AtomicLong(0); + + final FastFutureStore store = new FastFutureStore(count); + + List thList = new ArrayList(threadCount); + for (int c = 0; c < threadCount; ++c) { + Thread th = new Thread(new Runnable() { + @Override + public void run() { + + long t1 = System.currentTimeMillis(); + + List idList = new ArrayList(count / threadCount); + for (int ix = 0; ix < count / threadCount; ++ix) { + long id = store.put(new RpcFuture()); + idList.add(id); + } + + + for (int ix = 0; ix < count / threadCount; ++ix) { + long id = idList.get(ix); + RpcFuture fut = store.getAndRemove(id); + if (null == fut) { + throw new IllegalStateException("fut is null"); + } + } + + long t2 = System.currentTimeMillis(); + + result.addAndGet(t2 - t1); + } + }); + + thList.add(th); + th.start(); + } + + for (Thread th : thList) { + th.join(); + } + + return result.get(); + } + + /** + * 运行ConcurrentHashMap benchmark + * @param count + * @param threadCount + * @return + * @throws Exception + */ + private long runMap(final int count, final int threadCount) throws Exception { + final AtomicLong result = new AtomicLong(0); + + // 为了防止Hashmap扩容, 将每条线程需要执行的操作次数 / 0.75的结果作为map初始容量 + int singleThreadCount = count / threadCount; + int cap = (int) (singleThreadCount / 0.75); + final Map map = new ConcurrentHashMap(cap); + // final Map map = new HashMap(cap); + + final AtomicLong idGen = new AtomicLong(0); + + List thList = new ArrayList(threadCount); + for (int c = 0; c < threadCount; ++c) { + Thread th = new Thread(new Runnable() { + @Override + public void run() { + long t1 = System.currentTimeMillis(); + + List idList = new ArrayList(count / threadCount); + for (int ix = 0; ix < count / threadCount; ++ix) { + long id = idGen.getAndIncrement(); + idList.add(id); + map.put(id, new RpcFuture()); + } + + + for (int ix = 0; ix < count / threadCount; ++ix) { + long id = idList.get(ix); + RpcFuture fut = map.remove(id); + if (null == fut) { + throw new IllegalStateException("fut is null"); + } + } + + long t2 = System.currentTimeMillis(); + + result.addAndGet(t2 - t1); + } + }); + + thList.add(th); + th.start(); + } + + for (Thread th : thList) { + th.join(); + } + + return result.get(); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreTest.java new file mode 100644 index 00000000..c3601f60 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/FastFutureStoreTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wanghongfei on 2018/12/10. + */ +public class FastFutureStoreTest { + private FastFutureStore store = new FastFutureStore(10); + + @Test + public void testPutAndRemove() { + // 100 is much bigger than cap(10) + round(100); + } + + @Test + public void testMultipleRemoval() { + RpcFuture fut = new RpcFuture(); + // fut will be mapped to slot 0 + long logId = store.put(fut); + Assert.assertSame(fut, store.get(0)); + + // logId 10 will be mapped to slot 0 as well + RpcFuture removedFut = store.getAndRemove(10); + // cannot remove RpcFuture with logId 10 + Assert.assertNull(removedFut); + + // fut can only be removed with the correct logId + removedFut = store.getAndRemove(logId); + Assert.assertSame(removedFut, fut); + + removedFut = store.getAndRemove(logId); + Assert.assertNull(removedFut); + } + + private void round(int times) { + List elemList = new ArrayList(10); + List idList = new ArrayList(); + + for (int ix = 0; ix < times; ++ix) { + RpcFuture fut = new RpcFuture(); + Long id = store.put(fut); + + elemList.add(fut); + idList.add(id); + } + + for (int ix = 0; ix < idList.size(); ++ix) { + Long id = idList.get(ix); + RpcFuture fut = store.getAndRemove(id); + RpcFuture expected = elemList.get(ix); + + Assert.assertSame(fut, expected); + Assert.assertNull(store.get(id)); + } + + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcFutureTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcFutureTest.java new file mode 100644 index 00000000..334d93da --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcFutureTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; + +import com.baidu.brpc.ChannelInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.test.BaseMockitoTest; + +import io.netty.util.Timeout; + +public class RpcFutureTest extends BaseMockitoTest { + @Mock + private RpcClient rpcClient; + @Mock + private Timeout timeout; + @Mock + private ChannelInfo channelInfo; + @Mock + private BrpcChannel channelGroup; + @Mock + private RpcCallback rpcCallback; + @Mock + private Interceptor interceptor; + @Captor + private ArgumentCaptor throwableCaptor; + + private RpcMethodInfo methodInfo; + + private interface EchoService { + String echo(String message); + } + + @Before + public void init() throws Exception { + when(rpcClient.getInterceptors()).thenReturn(Collections.singletonList(interceptor)); + Class clazz = EchoService.class; + Method method = clazz.getMethod("echo", String.class); + this.methodInfo = new RpcMethodInfo(method); + reset(rpcCallback); + } + + @Test + public void testAsyncHandleSuccessfulResponse() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, rpcCallback, channelInfo, rpcClient); + Response response = new RpcResponse(); + response.setResult("hello world"); + rpcFuture.handleResponse(response); + verify(rpcCallback).success(eq("hello world")); + verify(interceptor).handleResponse(any(RpcResponse.class)); + assertThat(rpcFuture.get(), is(response.getResult())); + } + + @Test + public void testAsyncHandleFailResponse() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, rpcCallback, channelInfo, rpcClient); + Response response = new RpcResponse(); + RuntimeException ex = new RuntimeException("dummy"); + response.setException(ex); + rpcFuture.handleResponse(response); + verify(rpcCallback).fail(ex); + verify(interceptor).handleResponse(any(RpcResponse.class)); + try { + rpcFuture.get(); + } catch (RpcException ex2) { + Assert.assertTrue(ex2.getCause() == ex); + } + } + + @Test + public void testAsyncHandleNullResponse() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, rpcCallback, channelInfo, rpcClient); + rpcFuture.handleResponse(null); + verify(rpcCallback).fail(throwableCaptor.capture()); + Throwable t = throwableCaptor.getValue(); + assertThat(t, instanceOf(RpcException.class)); + verify(interceptor).handleResponse(null); + } + + @Test + public void testSyncHandleSuccessfulResponse() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, null, channelInfo, rpcClient); + RpcResponse response = new RpcResponse(); + response.setResult("hello world"); + rpcFuture.handleResponse(response); + String resp = rpcFuture.get(1, TimeUnit.SECONDS); + assertThat(resp, is("hello world")); + } + + @Test + public void testSyncHandleFailResponse() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, null, channelInfo, rpcClient); + RpcResponse response = new RpcResponse(); + RuntimeException ex = new RuntimeException("dummy"); + response.setException(ex); + rpcFuture.handleResponse(response); + try { + rpcFuture.get(1, TimeUnit.SECONDS); + } catch (RpcException ex2) { + Assert.assertTrue(ex2.getCause() == ex); + } + } + + @Test + public void testSyncHandleTimeout() throws Exception { + RpcFuture rpcFuture = new RpcFuture(timeout, methodInfo, null, channelInfo, rpcClient); + try { + rpcFuture.get(100, TimeUnit.MILLISECONDS); + } catch (RpcException ex2) { + Assert.assertTrue(ex2.getCode() == RpcException.TIMEOUT_EXCEPTION); + } + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcLongConnectionClientTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcLongConnectionClientTest.java new file mode 100644 index 00000000..926b033f --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcLongConnectionClientTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.server.ServiceManager; + +public class RpcLongConnectionClientTest { + + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + @Test + public void testBasic() { + RpcServer rpcServer = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000", + RpcOptionsUtils.getRpcClientOptions()); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + rpcClient.stop(); + + rpcServer.shutdown(); + } + + @Test + public void testHttpProto() { + RpcServerOptions serverOptions = RpcOptionsUtils.getRpcServerOptions(); + serverOptions.setProtocolType(Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + RpcServer rpcServer = new RpcServer(8000, serverOptions); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClientOptions clientOptions = RpcOptionsUtils.getRpcClientOptions(); + clientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + clientOptions.setMaxTryTimes(1); + clientOptions.setReadTimeoutMillis(1000000); + clientOptions.setWriteTimeoutMillis(1000000); + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000", clientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + + // test big message + String message = + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello"; + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage(message).build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals(message, response.getMessage()); + + // test small message + message = "hello"; + request = Echo.EchoRequest.newBuilder().setMessage(message).build(); + response = echoService.echo(request); + assertEquals(message, response.getMessage()); + + rpcClient.stop(); + rpcServer.shutdown(); + } + + @Test + public void testNsheadProto() { + RpcServerOptions serverOptions = RpcOptionsUtils.getRpcServerOptions(); + serverOptions.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + RpcServer rpcServer = new RpcServer(8000, serverOptions); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClientOptions clientOptions = RpcOptionsUtils.getRpcClientOptions(); + clientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000", clientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + + rpcClient.stop(); + rpcServer.shutdown(); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcProxyTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcProxyTest.java new file mode 100644 index 00000000..01cfe852 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcProxyTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.RpcOptionsUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.util.Map; + +public class RpcProxyTest { + + @Test + public void testRpcProxy() { + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8002", + RpcOptionsUtils.getRpcClientOptions()); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + System.out.println(echoService.toString()); + System.out.println(echoService.hashCode()); + rpcClient.shutdown(); + } + + @Test + public void testConstructor() throws Exception { + Class[] paramTypes = new Class[2]; + paramTypes[0] = RpcClient.class; + paramTypes[1] = Class.class; + Constructor constructor = BrpcProxy.class.getDeclaredConstructor(paramTypes); + constructor.setAccessible(true); + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8002", RpcOptionsUtils.getRpcClientOptions()); + BrpcProxy rpcProxy = (BrpcProxy) constructor.newInstance(rpcClient, EchoService.class); + rpcClient.shutdown(); + Assert.assertTrue(rpcProxy != null); + Map methodInfoMap = rpcProxy.getRpcMethodMap(); + Assert.assertTrue(methodInfoMap.size() > 0); + RpcMethodInfo rpcMethodInfo = methodInfoMap.entrySet().iterator().next().getValue(); + Assert.assertTrue(rpcMethodInfo != null); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcShortConnectionClientTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcShortConnectionClientTest.java new file mode 100644 index 00000000..b4d7b3a3 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/RpcShortConnectionClientTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client; + +import static org.junit.Assert.assertEquals; + + +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.instance.Endpoint; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.server.ServiceManager; + +public class RpcShortConnectionClientTest { + + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + @Test + public void testBasic() { + RpcServer rpcServer = new RpcServer(8001, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + Endpoint endPoint = new Endpoint("127.0.0.1", 8001); + RpcClientOptions rpcClientOptions = RpcOptionsUtils.getRpcClientOptions(); + rpcClientOptions.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_RANDOM); + rpcClientOptions.setChannelType(ChannelType.SHORT_CONNECTION); + RpcClient rpcClient = new RpcClient(endPoint, rpcClientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + rpcClient.stop(); + + rpcServer.shutdown(); + } + + @Test + public void testHttpProto() { + RpcServerOptions serverOptions = RpcOptionsUtils.getRpcServerOptions(); + serverOptions.setProtocolType(Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + RpcServer rpcServer = new RpcServer(8001, serverOptions); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClientOptions clientOptions = RpcOptionsUtils.getRpcClientOptions(); + clientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + clientOptions.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_RANDOM); + clientOptions.setChannelType(ChannelType.SHORT_CONNECTION); + + Endpoint endPoint = new Endpoint("127.0.0.1", 8001); + RpcClient rpcClient = new RpcClient(endPoint, clientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + + rpcClient.stop(); + rpcServer.shutdown(); + } + + @Test + public void testNsheadProto() { + RpcServerOptions serverOptions = RpcOptionsUtils.getRpcServerOptions(); + serverOptions.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + RpcServer rpcServer = new RpcServer(8001, serverOptions); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClientOptions clientOptions = RpcOptionsUtils.getRpcClientOptions(); + clientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + clientOptions.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_RANDOM); + clientOptions.setChannelType(ChannelType.SHORT_CONNECTION); + Endpoint endPoint = new Endpoint("127.0.0.1", 8001); + + RpcClient rpcClient = new RpcClient(endPoint, clientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + + rpcClient.stop(); + rpcServer.shutdown(); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/FairStrategyTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/FairStrategyTest.java new file mode 100644 index 00000000..bac4de17 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/FairStrategyTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.loadbalance; + +import java.util.LinkedList; +import java.util.Queue; + +import org.junit.Assert; +import org.junit.Test; + +public class FairStrategyTest extends FairStrategy { + + @Test + public void test1() { + Queue leafNodes = new LinkedList(); + Node node1 = new Node(1, 8, true); + Node node2 = new Node(1, 12, true); + Node node3 = new Node(1, 10, true); + leafNodes.add(node1); + leafNodes.add(node2); + leafNodes.add(node3); + Node root = generateWeightTreeByLeafNodes(leafNodes); + Node selected = searchNode(root, 6); + Assert.assertSame(node1, selected); + selected = searchNode(root, 18); + Assert.assertSame(node2, selected); + selected = searchNode(root, 22); + Assert.assertSame(node3, selected); + } + + @Test + public void test2() { + Queue leafNodes = new LinkedList(); + Node node1 = new Node(1, 8, true); + Node node2 = new Node(1, 12, true); + Node node3 = new Node(1, 8, true); + Node node4 = new Node(1, 2, true); + leafNodes.add(node1); + leafNodes.add(node2); + leafNodes.add(node3); + leafNodes.add(node4); + Node root = generateWeightTreeByLeafNodes(leafNodes); + Node selected = searchNode(root, 22); + Assert.assertSame(node3, selected); + selected = searchNode(root, 30); + Assert.assertSame(node4, selected); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/LoadBalanceTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/LoadBalanceTest.java new file mode 100644 index 00000000..d9c4fb17 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/LoadBalanceTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.loadbalance; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.interceptor.AbstractInterceptor; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Random; + +public class LoadBalanceTest { + + private static RpcServer rpcServer1; + private static RpcServer rpcServer2; + private static RpcServer rpcServer3; + private static String serviceUrl = "list://127.0.0.1:8000,127.0.0.1:8001,127.0.0.1:8002"; + + @BeforeClass + public static void beforeClass() { + rpcServer1 = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer1.registerService(new TestEchoService(100)); + rpcServer1.getInterceptors().add(new TestInterceptor(1)); + rpcServer1.start(); + rpcServer2 = new RpcServer(8001, RpcOptionsUtils.getRpcServerOptions()); + rpcServer2.registerService(new TestEchoService(200)); + rpcServer2.getInterceptors().add(new TestInterceptor(2)); + rpcServer2.start(); + rpcServer3 = new RpcServer(8002, RpcOptionsUtils.getRpcServerOptions()); + rpcServer3.registerService(new TestEchoService(300)); + rpcServer3.getInterceptors().add(new TestInterceptor(3)); + rpcServer3.start(); + } + + @AfterClass + public static void afterClass() { + if (rpcServer1 != null) { + rpcServer1.shutdown(); + } + if (rpcServer2 != null) { + rpcServer2.shutdown(); + } + if (rpcServer3 != null) { + rpcServer3.shutdown(); + } + } + + @Test + public void testRandomStrategy() { + RpcClientOptions clientOption = RpcOptionsUtils.getRpcClientOptions(); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_RANDOM); + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption); + final Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + final EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + for (int i = 0; i < 10; i++) { + echoService.echo(request); + } + rpcClient.stop(); + } + + @Test + public void testRoundRobinStrategy() { + RpcClientOptions clientOption = RpcOptionsUtils.getRpcClientOptions(); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_ROUND_ROBIN); + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, null); + final Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + final EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + for (int i = 0; i < 10; i++) { + echoService.echo(request); + } + rpcClient.stop(); + } + + @Test + public void testWeightStrategy() { + RpcClientOptions clientOption = RpcOptionsUtils.getRpcClientOptions(); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_WEIGHT); + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, null); + final Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + final EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + for (int i = 0; i < 10; i++) { + echoService.echo(request); + } + rpcClient.stop(); + } + + @Test + public void testFairStrategy() { + RpcClientOptions clientOption = RpcOptionsUtils.getRpcClientOptions(); + clientOption.setLatencyWindowSizeOfFairLoadBalance(10); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, null); + final Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + final EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + for (int i = 0; i < 20; i++) { + echoService.echo(request); + } + rpcClient.stop(); + } + + static class TestEchoService implements EchoService { + + private Random random = new Random(System.currentTimeMillis()); + + private int maxDelay; + + public TestEchoService(int maxDelay) { + this.maxDelay = maxDelay; + } + + @Override + public Echo.EchoResponse echo(Echo.EchoRequest request) { + String message = request.getMessage(); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage(message).build(); + try { + Thread.sleep(random.nextInt(maxDelay)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return response; + } + } + + static class TestInterceptor extends AbstractInterceptor { + + private int serverId; + + public TestInterceptor(int serverId) { + this.serverId = serverId; + } + + @Override + public boolean handleRequest(Request request) { + System.out.println("------" + serverId + " called------"); + return true; + } + + @Override + public void handleResponse(Response response) { + + } + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/RandomStrategyTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/RandomStrategyTest.java new file mode 100644 index 00000000..8260e2f1 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/loadbalance/RandomStrategyTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.client.loadbalance; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.junit.*; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.channel.BrpcChannel; +import com.baidu.brpc.client.channel.BrpcChannelFactory; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.server.RpcServer; + +public class RandomStrategyTest { + private static RpcServer rpcServer1; + private static RpcServer rpcServer2; + private static RpcServer rpcServer3; + + private static BrpcChannel instance1; + private static BrpcChannel instance2; + private static BrpcChannel instance3; + + private static String serviceUrl = "list://127.0.0.1:8000,127.0.0.1:8001,127.0.0.1:8002"; + private static RpcClient rpcClient; + + @Before + public void before() { + rpcServer1 = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer1.registerService(new LoadBalanceTest.TestEchoService(100)); + rpcServer1.getInterceptors().add(new LoadBalanceTest.TestInterceptor(1)); + rpcServer1.start(); + rpcServer2 = new RpcServer(8001, RpcOptionsUtils.getRpcServerOptions()); + rpcServer2.registerService(new LoadBalanceTest.TestEchoService(200)); + rpcServer2.getInterceptors().add(new LoadBalanceTest.TestInterceptor(2)); + rpcServer2.start(); + rpcServer3 = new RpcServer(8002, RpcOptionsUtils.getRpcServerOptions()); + rpcServer3.registerService(new LoadBalanceTest.TestEchoService(300)); + rpcServer3.getInterceptors().add(new LoadBalanceTest.TestInterceptor(3)); + rpcServer3.start(); + + rpcClient = new RpcClient(serviceUrl, RpcOptionsUtils.getRpcClientOptions()); + instance1 = BrpcChannelFactory.createChannel(new ServiceInstance("127.0.0.1", 8000), rpcClient); + instance2 = BrpcChannelFactory.createChannel(new ServiceInstance("127.0.0.1", 8001), rpcClient); + instance3 = BrpcChannelFactory.createChannel(new ServiceInstance("127.0.0.1", 8002), rpcClient); + } + + @After + public void after() { + if (instance1 != null) { + instance1.close(); + } + if (instance2 != null) { + instance2.close(); + } + if (instance3 != null) { + instance3.close(); + } + if (rpcClient != null) { + rpcClient.stop(); + } + if (rpcServer1 != null) { + rpcServer1.shutdown(); + } + if (rpcServer2 != null) { + rpcServer2.shutdown(); + } + if (rpcServer3 != null) { + rpcServer3.shutdown(); + } + } + + @Test + public void testSelectInstance() { + CopyOnWriteArrayList instances = new CopyOnWriteArrayList(); + instances.add(instance1); + instances.add(instance2); + instances.add(instance3); + RandomStrategy randomStrategy = new RandomStrategy(); + BrpcChannel instance = randomStrategy.selectInstance(null, instances, null); + Assert.assertTrue(instance != null); + + Set selectedInstances = new HashSet(); + selectedInstances.add(instance3); + instance = randomStrategy.selectInstance(null, instances, selectedInstances); + Assert.assertTrue(instance.getServiceInstance().getPort() != instance3.getServiceInstance().getPort()); + + selectedInstances.add(instance2); + instance = randomStrategy.selectInstance(null, instances, selectedInstances); + Assert.assertTrue(instance.getServiceInstance().getPort() == instance1.getServiceInstance().getPort()); + + selectedInstances.add(instance1); + instance = randomStrategy.selectInstance(null, instances, selectedInstances); + Assert.assertTrue(instance != null); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/client/pool/ChannelPoolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/client/pool/ChannelPoolTest.java new file mode 100644 index 00000000..7ac86c73 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/client/pool/ChannelPoolTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.client.pool; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import com.baidu.brpc.client.channel.BrpcChannel; +import io.netty.channel.Channel; + +public class ChannelPoolTest { + + private GenericObjectPool pool; + + @Before + public void before() throws Exception { + ChannelPooledObjectFactory pooledObjectFactory = + spy(new ChannelPooledObjectFactory(mock(BrpcChannel.class), "127.0.0.1", 8000)); + doAnswer(new Answer() { + public Channel answer(InvocationOnMock invocation) { + return mock(Channel.class); + } + }).when(pooledObjectFactory).create(); + GenericObjectPoolConfig conf = new GenericObjectPoolConfig(); + conf.setMaxTotal(5); + conf.setMaxIdle(5); + conf.setMinIdle(3); + pool = new GenericObjectPool(pooledObjectFactory, conf); + } + + @After + public void after() { + if (pool != null) { + pool.close(); + } + } + + @Test + public void test() throws Exception { + pool.preparePool(); + assertThat(pool.getNumIdle(), is(3)); + Channel channel1 = pool.borrowObject(); + Channel channel2 = pool.borrowObject(); + assertThat(pool.getNumActive(), is(2)); + Channel channel3 = pool.borrowObject(); + pool.returnObject(channel1); + pool.returnObject(channel2); + pool.returnObject(channel3); + assertThat(pool.getNumIdle(), is(3)); + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/compress/CompressManagerTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/compress/CompressManagerTest.java new file mode 100644 index 00000000..f5c5bec9 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/compress/CompressManagerTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.Options; +import org.junit.Assert; +import org.junit.Test; + +public class CompressManagerTest { + @Test + public void testGetCompress() { + CompressManager compressManager = CompressManager.getInstance(); + Compress compress = compressManager.getCompress(Options.CompressType.COMPRESS_TYPE_NONE_VALUE); + Assert.assertNotNull(compress); + compress = compressManager.getCompress(Options.CompressType.COMPRESS_TYPE_GZIP_VALUE); + Assert.assertNotNull(compress); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/compress/GzipCompressTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/compress/GzipCompressTest.java new file mode 100644 index 00000000..7676319a --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/compress/GzipCompressTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.jprotobuf.EchoResponse; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import io.netty.buffer.ByteBuf; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.Method; + +public class GzipCompressTest { + private static ProtobufRpcMethodInfo protobufRpcMethodInfo; + private static JprotobufRpcMethodInfo jprotobufRpcMethodInfo; + private static GzipCompress compress; + + @BeforeClass + public static void beforeClass() throws NoSuchMethodException { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + protobufRpcMethodInfo = new ProtobufRpcMethodInfo(method); + Method method1 = com.baidu.brpc.protocol.jprotobuf.EchoService.class.getMethod("echo", + EchoRequest.class); + jprotobufRpcMethodInfo = new JprotobufRpcMethodInfo(method1); + compress = new GzipCompress(); + } + + @Test + public void testCompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testUncompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + Echo.EchoRequest request2 = (Echo.EchoRequest) compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + System.out.println(request2.getMessage()); + } + + @Test + public void testCompressInputForJprotobuf() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testProtobufEncodeRequestJprotobufDecodeRequest() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, jprotobufRpcMethodInfo); + EchoRequest request2 = (EchoRequest) object; + System.out.println(request2.getMessage()); + } + + @Test + public void testJprotobufEncodeRequestProtobufDecodeRequest() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + Echo.EchoRequest request1 = (Echo.EchoRequest) object; + System.out.println(request1.getMessage()); + } + + @Test + public void testProtobufEncodeResponseJprotobufDecodeResponse() throws IOException { + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressOutput(response, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, jprotobufRpcMethodInfo); + EchoResponse response1 = (EchoResponse) object; + System.out.println(response.getMessage()); + } + + @Test + public void testJprotobufEncodeResponseProtobufDecodeResponse() throws IOException { + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + ByteBuf byteBuf = compress.compressOutput(response, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, protobufRpcMethodInfo); + Echo.EchoResponse response1 = (Echo.EchoResponse) object; + System.out.println(response1.getMessage()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/compress/NoneCompressTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/compress/NoneCompressTest.java new file mode 100644 index 00000000..3f1f6276 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/compress/NoneCompressTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.jprotobuf.EchoResponse; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import io.netty.buffer.ByteBuf; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.Method; + +public class NoneCompressTest { + private static ProtobufRpcMethodInfo protobufRpcMethodInfo; + private static JprotobufRpcMethodInfo jprotobufRpcMethodInfo; + private static NoneCompress compress; + + @BeforeClass + public static void beforeClass() throws NoSuchMethodException { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + protobufRpcMethodInfo = new ProtobufRpcMethodInfo(method); + Method method1 = com.baidu.brpc.protocol.jprotobuf.EchoService.class.getMethod("echo", + EchoRequest.class); + jprotobufRpcMethodInfo = new JprotobufRpcMethodInfo(method1); + compress = new NoneCompress(); + } + + @Test + public void testCompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testUncompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + Echo.EchoRequest request2 = (Echo.EchoRequest) compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + System.out.println(request2.getMessage()); + } + + @Test + public void testCompressInputForJprotobuf() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testProtobufEncodeRequestJprotobufDecodeRequest() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, jprotobufRpcMethodInfo); + EchoRequest request2 = (EchoRequest) object; + System.out.println(request2.getMessage()); + } + + @Test + public void testJprotobufEncodeRequestProtobufDecodeRequest() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + Echo.EchoRequest request1 = (Echo.EchoRequest) object; + System.out.println(request1.getMessage()); + } + + @Test + public void testProtobufEncodeResponseJprotobufDecodeResponse() throws IOException { + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressOutput(response, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, jprotobufRpcMethodInfo); + EchoResponse response1 = (EchoResponse) object; + System.out.println(response.getMessage()); + } + + @Test + public void testJprotobufEncodeResponseProtobufDecodeResponse() throws IOException { + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + ByteBuf byteBuf = compress.compressOutput(response, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, protobufRpcMethodInfo); + Echo.EchoResponse response1 = (Echo.EchoResponse) object; + System.out.println(response1.getMessage()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/compress/SnappyCompressTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/compress/SnappyCompressTest.java new file mode 100644 index 00000000..b432bb2b --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/compress/SnappyCompressTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.jprotobuf.EchoResponse; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import io.netty.buffer.ByteBuf; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.Method; + +public class SnappyCompressTest { + private static ProtobufRpcMethodInfo protobufRpcMethodInfo; + private static JprotobufRpcMethodInfo jprotobufRpcMethodInfo; + private static SnappyCompress compress; + + @BeforeClass + public static void beforeClass() throws NoSuchMethodException { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + protobufRpcMethodInfo = new ProtobufRpcMethodInfo(method); + Method method1 = com.baidu.brpc.protocol.jprotobuf.EchoService.class.getMethod("echo", + EchoRequest.class); + jprotobufRpcMethodInfo = new JprotobufRpcMethodInfo(method1); + compress = new SnappyCompress(); + } + + @Test + public void testCompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testUncompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + Echo.EchoRequest request2 = (Echo.EchoRequest) compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + System.out.println(request2.getMessage()); + } + + @Test + public void testCompressInputForJprotobuf() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testProtobufEncodeRequestJprotobufDecodeRequest() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, jprotobufRpcMethodInfo); + EchoRequest request2 = (EchoRequest) object; + System.out.println(request2.getMessage()); + } + + @Test + public void testJprotobufEncodeRequestProtobufDecodeRequest() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + Echo.EchoRequest request1 = (Echo.EchoRequest) object; + System.out.println(request1.getMessage()); + } + + @Test + public void testProtobufEncodeResponseJprotobufDecodeResponse() throws IOException { + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressOutput(response, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, jprotobufRpcMethodInfo); + EchoResponse response1 = (EchoResponse) object; + System.out.println(response.getMessage()); + } + + @Test + public void testJprotobufEncodeResponseProtobufDecodeResponse() throws IOException { + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + ByteBuf byteBuf = compress.compressOutput(response, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, protobufRpcMethodInfo); + Echo.EchoResponse response1 = (Echo.EchoResponse) object; + System.out.println(response1.getMessage()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/compress/ZlibCompressTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/compress/ZlibCompressTest.java new file mode 100644 index 00000000..1919d058 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/compress/ZlibCompressTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.compress; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.jprotobuf.EchoResponse; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.JprotobufRpcMethodInfo; +import com.baidu.brpc.ProtobufRpcMethodInfo; +import io.netty.buffer.ByteBuf; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.Method; + +public class ZlibCompressTest { + private static ProtobufRpcMethodInfo protobufRpcMethodInfo; + private static JprotobufRpcMethodInfo jprotobufRpcMethodInfo; + private static ZlibCompress compress; + + @BeforeClass + public static void beforeClass() throws NoSuchMethodException { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + protobufRpcMethodInfo = new ProtobufRpcMethodInfo(method); + Method method1 = com.baidu.brpc.protocol.jprotobuf.EchoService.class.getMethod("echo", + EchoRequest.class); + jprotobufRpcMethodInfo = new JprotobufRpcMethodInfo(method1); + compress = new ZlibCompress(); + } + + @Test + public void testCompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testUncompressInputForProtobuf() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + Echo.EchoRequest request2 = (Echo.EchoRequest) compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + System.out.println(request2.getMessage()); + } + + @Test + public void testCompressInputForJprotobuf() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + } + + @Test + public void testProtobufEncodeRequestJprotobufDecodeRequest() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressInput(request, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, jprotobufRpcMethodInfo); + EchoRequest request2 = (EchoRequest) object; + System.out.println(request2.getMessage()); + } + + @Test + public void testJprotobufEncodeRequestProtobufDecodeRequest() throws IOException { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + ByteBuf byteBuf = compress.compressInput(request, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressInput(byteBuf, protobufRpcMethodInfo); + Echo.EchoRequest request1 = (Echo.EchoRequest) object; + System.out.println(request1.getMessage()); + } + + @Test + public void testProtobufEncodeResponseJprotobufDecodeResponse() throws IOException { + Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage("hello").build(); + ByteBuf byteBuf = compress.compressOutput(response, protobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, jprotobufRpcMethodInfo); + EchoResponse response1 = (EchoResponse) object; + System.out.println(response.getMessage()); + } + + @Test + public void testJprotobufEncodeResponseProtobufDecodeResponse() throws IOException { + EchoResponse response = new EchoResponse(); + response.setMessage("hello"); + ByteBuf byteBuf = compress.compressOutput(response, jprotobufRpcMethodInfo); + System.out.println(byteBuf.readableBytes()); + + Object object = compress.uncompressOutput(byteBuf, protobufRpcMethodInfo); + Echo.EchoResponse response1 = (Echo.EchoResponse) object; + System.out.println(response1.getMessage()); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/interceptor/InterceptorTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/interceptor/InterceptorTest.java new file mode 100644 index 00000000..c16020bf --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/interceptor/InterceptorTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.interceptor; + +import com.baidu.brpc.RpcOptionsUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.server.RpcServer; + +public class InterceptorTest { + + private static RpcServer rpcServer; + + private static boolean[] flags = new boolean[4]; + + @BeforeClass + public static void beforeClass() { + rpcServer = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.getInterceptors().add(new Interceptor() { + @Override + public boolean handleRequest(Request request) { + System.out.println("server handleRequest1"); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + flags[0] = true; + chain.intercept(request, response); + } + + @Override + public void handleResponse(Response response) { + System.out.println("server handleResponse1"); + } + }); + + rpcServer.getInterceptors().add(new Interceptor() { + @Override + public boolean handleRequest(Request request) { + System.out.println("server handleRequest2"); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + flags[1] = true; + chain.intercept(request, response); + } + + @Override + public void handleResponse(Response response) { + System.out.println("server handleResponse2"); + } + }); + rpcServer.start(); + } + + @AfterClass + public static void afterClass() { + if (rpcServer != null) { + rpcServer.shutdown(); + } + } + + @Test + public void test() { + for (int i = 0; i < 4; ++i) { + Assert.assertFalse(flags[i]); + } + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000", + RpcOptionsUtils.getRpcClientOptions()); + rpcClient.getInterceptors().add(new Interceptor() { + @Override + public boolean handleRequest(Request request) { + System.out.println("client handleRequest1"); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + flags[2] = true; + chain.intercept(request, response); + } + + @Override + public void handleResponse(Response response) { + System.out.println("client handleResponse1"); + } + }); + + rpcClient.getInterceptors().add(new Interceptor() { + @Override + public boolean handleRequest(Request request) { + System.out.println("client handleRequest2"); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + flags[3] = true; + chain.intercept(request, response); + } + + @Override + public void handleResponse(Response response) { + System.out.println("client handleResponse2"); + } + }); + + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + final String message = "hello"; + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage(message).build(); + Echo.EchoResponse response = echoService.echo(request); + Assert.assertEquals(response.getMessage(), message); + for (int i = 0; i < 4; ++i) { + Assert.assertTrue(flags[i]); + } + rpcClient.stop(); + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/naming/BrpcURITest.java b/brpc-java-core/src/test/java/com/baidu/brpc/naming/BrpcURITest.java new file mode 100644 index 00000000..402f68ef --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/naming/BrpcURITest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming; + +import org.junit.Assert; +import org.junit.Test; + +public class BrpcURITest { + @Test + public void testBns() { + String bns = "bns://test.com"; + BrpcURL uri = new BrpcURL(bns); + Assert.assertTrue(uri.getSchema().equals("bns")); + Assert.assertTrue(uri.getHostPorts().equals("test.com")); + } + + @Test + public void testList() { + String serviceUrl = "list://127.0.0.1:8002,127.0.0.1:8003"; + BrpcURL uri = new BrpcURL(serviceUrl); + Assert.assertTrue(uri.getSchema().equals("list")); + Assert.assertTrue(uri.getHostPorts().equals("127.0.0.1:8002,127.0.0.1:8003")); + } + + @Test + public void testFile() { + String serviceUrl = "file:///home/ubuntu/test.config"; + BrpcURL uri = new BrpcURL(serviceUrl); + Assert.assertTrue(uri.getSchema().equals("file")); + Assert.assertTrue(uri.getHostPorts().equals("")); + Assert.assertTrue(uri.getPath().equals("/home/ubuntu/test.config")); + } + + @Test + public void testDns() { + String serviceUrl = "dns://weibo.com"; + BrpcURL uri = new BrpcURL(serviceUrl); + Assert.assertTrue(uri.getSchema().equals("dns")); + Assert.assertTrue(uri.getHostPorts().equals("weibo.com")); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/naming/DnsNamingServiceTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/naming/DnsNamingServiceTest.java new file mode 100644 index 00000000..d38a0941 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/naming/DnsNamingServiceTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.junit.Test; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.test.BaseMockitoTest; + +public class DnsNamingServiceTest extends BaseMockitoTest { + + @Test + public void testAll() { + String serverList = "dns://127.0.0.1:8888"; + DnsNamingService namingService = new DnsNamingService(new BrpcURL(serverList)); + assertThat(namingService.getHostPort(), is("127.0.0.1:8888")); + List instances = namingService.lookup(null); + assertThat(instances, hasItems(new ServiceInstance("127.0.0.1", 8888))); + namingService.unsubscribe(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptyServerList() { + DnsNamingService namingService = new DnsNamingService(new BrpcURL("")); + namingService.lookup(null); + } + +} \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/naming/FileNamingServiceTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/naming/FileNamingServiceTest.java new file mode 100644 index 00000000..bf60fe01 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/naming/FileNamingServiceTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.net.URL; +import java.util.List; + +import org.junit.Test; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.test.BaseMockitoTest; + +public class FileNamingServiceTest extends BaseMockitoTest { + + @Test + public void testAll() throws Exception { + URL url = Thread.currentThread().getContextClassLoader().getResource("test_server_list.txt"); + String serverList = url.getFile(); + FileNamingService namingService = new FileNamingService(new BrpcURL("file://" + serverList)); + + List instances = namingService.lookup(null); + assertThat(instances.size(), is(1)); + assertThat(instances, hasItems( + new ServiceInstance("127.0.0.1", 8002) + )); + namingService.unsubscribe(null); + } +} \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/naming/ListNamingServiceTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/naming/ListNamingServiceTest.java new file mode 100644 index 00000000..7e9669b5 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/naming/ListNamingServiceTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming; + +import java.util.List; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.test.BaseMockitoTest; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class ListNamingServiceTest extends BaseMockitoTest { + + @Test + public void testUpdateServerList() { + String serverList = "list://1.1.1.1:1111,2.2.2.2:2222"; + ListNamingService namingService = new ListNamingService(new BrpcURL(serverList)); + List instances = namingService.lookup(null); + assertThat(instances, hasItems( + new ServiceInstance("1.1.1.1", 1111), + new ServiceInstance("2.2.2.2", 2222) + )); + assertThat(instances.size(), is(2)); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateServerListInvalid1() { + ListNamingService namingService = new ListNamingService(new BrpcURL("")); + namingService.lookup(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateServerListInvalid2() { + ListNamingService namingService = new ListNamingService(new BrpcURL("1.1.1.1,2.2.2.2")); + namingService.lookup(null); + } + +} \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpJsonProtocolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpJsonProtocolTest.java new file mode 100644 index 00000000..08001d3b --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpJsonProtocolTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; + +import org.junit.Assert; +import org.junit.Test; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.protocol.HttpRequest; +import com.baidu.brpc.protocol.HttpResponse; +import com.baidu.brpc.protocol.Options.ProtocolType; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import com.baidu.brpc.protocol.http.json.HelloWorldService; +import com.baidu.brpc.protocol.http.json.HelloWorldServiceImpl; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ByteBufUtils; +import com.google.gson.Gson; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; + +public class HttpJsonProtocolTest { + + private HttpRpcProtocol protocol = new HttpRpcProtocol( + ProtocolType.PROTOCOL_HTTP_JSON_VALUE, "utf-8"); + + @Test + public void testEncodeHttpRequest() throws Exception { + Request request = new HttpRequest(); + request.setTargetMethod(HelloWorldService.class.getMethods()[0]); + request.setArgs(new Object[] {"hello"}); + request.setLogId(1L); + ByteBuf buf = protocol.encodeRequest(request); + Assert.assertTrue(buf.readableBytes() > 0); + System.out.println(buf.readableBytes()); + System.out.println(ByteBufUtils.byteBufToString(buf)); + } + + @Test + public void testDecodeHttpRequest() { + ServiceManager serviceManager = ServiceManager.getInstance(); + serviceManager.registerService(new HelloWorldServiceImpl(), null); + ByteBuf content = Unpooled.wrappedBuffer(new Gson().toJson("hello").getBytes()); + + FullHttpRequest fullHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, + "/HelloWorldService/hello?k=v", content); + fullHttpRequest.headers().set("log-id", 1); + fullHttpRequest.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8"); + + Request request = protocol.decodeRequest(fullHttpRequest); + + assertEquals("HelloWorldService", request.getRpcMethodInfo().getServiceName()); + assertEquals("hello", request.getRpcMethodInfo().getMethodName()); + assertEquals(HelloWorldService.class.getMethods()[0], request.getTargetMethod()); + assertEquals(HelloWorldServiceImpl.class, request.getTarget().getClass()); + } + + @Test + public void testEncodeHttpResponse() throws Exception { + HttpRequest request = new HttpRequest(); + String contentType = "application/json; charset=utf-8"; + request.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType); + request.headers().set(HttpHeaderNames.CONTENT_ENCODING, "utf-8"); + request.headers().set("protocol-type", "30"); + Response response = new HttpResponse(); + response.setResult("hello world"); + protocol.encodeResponse(request, response); + } + + public byte[] encodeBody(Object body) throws Exception { + Method method = protocol.getClass().getDeclaredMethod("encodeBody", int.class, String.class, + Object.class, RpcMethodInfo.class); + method.setAccessible(true); + Object r = method.invoke(protocol, ProtocolType.PROTOCOL_HTTP_JSON_VALUE, "utf-8", body, + new RpcMethodInfo(HelloWorldService.class.getMethods()[0])); + return (byte[]) r; + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpProtoProtocolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpProtoProtocolTest.java new file mode 100644 index 00000000..8573c1a6 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/HttpProtoProtocolTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import com.baidu.brpc.protocol.*; +import org.junit.Assert; +import org.junit.Test; + +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.protocol.Options.ProtocolType; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ByteBufUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; + +public class HttpProtoProtocolTest { + + private HttpRpcProtocol protocol = new HttpRpcProtocol( + ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE, "utf-8"); + + @Test + public void testEncodeHttpRequest() throws Exception { + Request request = new HttpRequest(); + request.setTargetMethod(EchoService.class.getMethods()[0]); + request.setArgs(new Object[] {Echo.EchoRequest.newBuilder().setMessage("hello").build()}); + request.setLogId(1L); + request.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + request.setKvAttachment(new HashMap()); + request.getKvAttachment().put("key", "value"); + ByteBuf buf = protocol.encodeRequest(request); + Assert.assertTrue(buf.readableBytes() > 0); + System.out.println(buf.readableBytes()); + System.out.println(ByteBufUtils.byteBufToString(buf)); + } + + @Test + public void testDecodeHttpRequest() throws Exception { + ServiceManager serviceManager = ServiceManager.getInstance(); + serviceManager.registerService(new EchoServiceImpl(), null); + + ByteBuf content = Unpooled.wrappedBuffer(encodeBody( + Echo.EchoRequest.newBuilder().setMessage("hello").build())); + + FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, + "/example.EchoService/Echo", content); + httpRequest.headers().set("log-id", 1); + httpRequest.setUri("/example.EchoService/Echo"); + httpRequest.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/proto; charset=utf-8"); + httpRequest.headers().set("key", "value"); + + Request request = protocol.decodeRequest(httpRequest); + assertEquals("example.EchoService", request.getRpcMethodInfo().getServiceName()); + assertEquals("Echo", request.getRpcMethodInfo().getMethodName()); + assertEquals(EchoService.class.getMethods()[0], request.getTargetMethod()); + assertEquals(EchoServiceImpl.class, request.getTarget().getClass()); + assertEquals(request.getKvAttachment().get("key"), "value"); + } + + @Test + public void testEncodeHttpResponse() throws Exception { + HttpRequest request = new HttpRequest(); + String contentType = "application/proto; charset=utf-8"; + request.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType); + request.headers().set(HttpHeaderNames.CONTENT_ENCODING, "utf-8"); + request.headers().set(HttpRpcProtocol.PROTOCOL_TYPE, + Options.ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + request.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + Response response = new HttpResponse(); + response.setResult(Echo.EchoResponse.newBuilder().setMessage("hello").build()); + + ProtobufRpcMethodInfo methodInfo = new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0]); + methodInfo.setTarget(new EchoServiceImpl()); + response.setRpcMethodInfo(methodInfo); + + protocol.encodeResponse(request, response); + } + + public byte[] encodeBody(Object body) throws Exception { + Method method = protocol.getClass().getDeclaredMethod("encodeBody", int.class, String.class, + Object.class, RpcMethodInfo.class); + method.setAccessible(true); + Object r = method.invoke(protocol, ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE, "utf-8", + body, new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + + return (byte[]) r; + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldService.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldService.java new file mode 100644 index 00000000..844ec443 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldService.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http.json; + +import com.baidu.brpc.protocol.BrpcMeta; + +public interface HelloWorldService { + + @BrpcMeta(serviceName = "HelloWorldService", methodName = "hello") + String hello(String request); + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldServiceImpl.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldServiceImpl.java new file mode 100644 index 00000000..5b1d8af0 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/http/json/HelloWorldServiceImpl.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.http.json; + +public class HelloWorldServiceImpl implements HelloWorldService { + + @Override + public String hello(String request) { + + return "hello " + request; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoRequest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoRequest.java new file mode 100644 index 00000000..43e7cc71 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.jprotobuf; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoResponse.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoResponse.java new file mode 100644 index 00000000..534c5eda --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.jprotobuf; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoService.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoService.java new file mode 100644 index 00000000..2a7c3d2f --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.jprotobuf; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoServiceAsync.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoServiceAsync.java new file mode 100644 index 00000000..3255ef83 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/jprotobuf/EchoServiceAsync.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.jprotobuf; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +public interface EchoServiceAsync extends EchoService { + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NSHeadTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NSHeadTest.java new file mode 100644 index 00000000..d3ea2722 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NSHeadTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import com.baidu.brpc.exceptions.BadSchemaException; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +public class NSHeadTest { + + @Test + public void fromByteBuf() throws BadSchemaException { + byte[] bytes = new byte[]{ + -22, 0, 1, 0, 123, 0, 0, 0, 108, 111, 110, 103, 101, 114, 45, 116, 104, + 97, 110, 45, 115, 105, 120, 116, -108, -109, 112, -5, 0, 0, 0, 0, 41, 9, 0, 0 + }; + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + NSHead head = NSHead.fromByteBuf(buf); + assertThat(head.id, equalTo((short) 234)); + assertThat(head.logId, equalTo(123)); + assertThat(head.version, equalTo((short) 1)); + assertThat(head.provider, equalTo("longer-than-sixt")); // een discard + assertThat(head.bodyLength, equalTo(2345)); + } + + @Test + public void toBytes() { + byte[] bytes = new byte[]{ + -22, 0, 1, 0, 123, 0, 0, 0, 108, 111, 110, 103, 101, 114, 45, 116, 104, + 97, 110, 45, 115, 105, 120, 116, -108, -109, 112, -5, 0, 0, 0, 0, 41, 9, 0, 0 + }; + NSHead head = new NSHead(123, (short) 234, (short) 1, "longer-than-sixteen", 2345); + byte[] serialized = head.toBytes(); + assertThat(serialized, equalTo(bytes)); + } +} \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NsHeadRpcProtocolProtobufTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NsHeadRpcProtocolProtobufTest.java new file mode 100644 index 00000000..1d7ec82e --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/nshead/NsHeadRpcProtocolProtobufTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.nshead; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; + +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.Echo.EchoRequest; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.server.ServiceManager; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class NsHeadRpcProtocolProtobufTest { + + private NSHeadRpcProtocol protocol = new NSHeadProtobufProtocol("utf-8"); + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + @Test + public void testEncodeRequest() throws Exception { + + EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + + RpcRequest rpcRequest = new RpcRequest(); + rpcRequest.setArgs(new Object[] {request}); + rpcRequest.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + rpcRequest.setLogId(3L); + NSHeadMeta nsHeadMeta = rpcRequest.getRpcMethodInfo().getNsHeadMeta(); + rpcRequest.setNsHead(new NSHead(3, nsHeadMeta.id(), + nsHeadMeta.version(), nsHeadMeta.provider(), 0)); + + ByteBuf byteBuf = protocol.encodeRequest(rpcRequest); + + NSHead nsHead = NSHead.fromByteBuf(byteBuf); + + assertEquals(3, nsHead.logId); + assertEquals("", nsHead.provider); + assertEquals(byteBuf.readableBytes(), nsHead.bodyLength); + } + + + @Test + public void testDecodeRequestSuccess() throws Exception { + ServiceManager.getInstance().getServiceMap().clear(); + + ServiceManager.getInstance().registerService(new EchoServiceImpl(), null); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage("hello").build(); + + NSHeadPacket packet = new NSHeadPacket(); + byte[] body = encodeBody(response, EchoService.class.getMethods()[0]); + packet.setNsHead(new NSHead(1, body.length)); + packet.setBodyBuf(Unpooled.wrappedBuffer(body)); + Request request = protocol.decodeRequest(packet); + + assertEquals(EchoService.class.getMethods()[0], request.getTargetMethod()); + assertEquals(EchoServiceImpl.class, request.getTarget().getClass()); + } + + + @Test + public void testEncodeResponse() throws Exception { + + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage("hello").build(); + + RpcResponse rpcResponse = new RpcResponse(); + rpcResponse.setLogId(4L); + rpcResponse.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + rpcResponse.setResult(response); + + ByteBuf byteBuf = protocol.encodeResponse(null, rpcResponse); + + NSHead nsHead = NSHead.fromByteBuf(byteBuf); + + assertEquals(4, nsHead.logId); + assertEquals(byteBuf.readableBytes(), nsHead.bodyLength); + } + + private byte[] encodeBody(Object body, Method invokeMethod) throws Exception { + + Method method = protocol.getClass().getDeclaredMethod("encodeBody", Object.class, RpcMethodInfo.class); + method.setAccessible(true); + Object r = method.invoke(protocol, body, new ProtobufRpcMethodInfo(invokeMethod)); + + return (byte[]) r; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoService.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoService.java new file mode 100644 index 00000000..9437b51d --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoService.java @@ -0,0 +1,14 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.protocol.BrpcMeta; +import com.baidu.brpc.protocol.standard.Echo; + +public interface EchoService { + + /** + * serviceName是类名,不需要加包名 + * methodName是proto中方法定义的index,下标从0开始 + */ + @BrpcMeta(serviceName = "EchoService", methodName = "0") + Echo.EchoResponse echo(Echo.EchoRequest request); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoServiceImpl.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoServiceImpl.java new file mode 100644 index 00000000..39675844 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/EchoServiceImpl.java @@ -0,0 +1,16 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.Echo.EchoRequest; +import com.baidu.brpc.protocol.standard.Echo.EchoResponse; + +public class EchoServiceImpl implements EchoService { + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage(message).build(); + return response; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocolTest.java new file mode 100644 index 00000000..05343849 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/pbrpc/PublicPbrpcProtocolTest.java @@ -0,0 +1,83 @@ +package com.baidu.brpc.protocol.pbrpc; + +import com.baidu.brpc.ProtobufRpcMethodInfo; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.protocol.RpcResponse; +import com.baidu.brpc.protocol.nshead.NSHead; +import com.baidu.brpc.protocol.standard.Echo.EchoRequest; +import com.baidu.brpc.protocol.standard.Echo.EchoResponse; +import com.baidu.brpc.server.ServiceManager; +import io.netty.buffer.ByteBuf; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PublicPbrpcProtocolTest { + + private PublicPbrpcProtocol protocol = new PublicPbrpcProtocol(); + + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + + @Test + public void testEncodeRequest() throws Exception { + EchoRequest request = buildRequest(); + + RpcRequest rpcRequest = new RpcRequest(); + rpcRequest.setArgs(new Object[] {request}); + rpcRequest.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + rpcRequest.setLogId(3L); + rpcRequest.setNsHead(new NSHead((int) rpcRequest.getLogId(), 0)); + rpcRequest.setTargetMethod(EchoService.class.getMethods()[0]); + rpcRequest.setServiceName("EchoService"); + ByteBuf byteBuf = protocol.encodeRequest(rpcRequest); + NSHead nsHead = NSHead.fromByteBuf(byteBuf); + + assertEquals(3, nsHead.logId); + assertEquals(byteBuf.readableBytes(), nsHead.bodyLength); + } + + @Test + public void testEncodeResponse() throws Exception { + + EchoResponse result = buildResponse(); + + RpcResponse rpcResponse = new RpcResponse(); + rpcResponse.setLogId(4L); + rpcResponse.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + rpcResponse.setResult(result); + + Request rpcRequest = new RpcRequest(); + rpcRequest.setLogId(4L); + rpcRequest.setRpcMethodInfo(new ProtobufRpcMethodInfo(EchoService.class.getMethods()[0])); + + ByteBuf byteBuf = protocol.encodeResponse(rpcRequest, rpcResponse); + NSHead nsHead = NSHead.fromByteBuf(byteBuf); + + assertEquals(4, nsHead.logId); + assertEquals(byteBuf.readableBytes(), nsHead.bodyLength); + } + + + public EchoRequest buildRequest() { + + EchoRequest.Builder builder = EchoRequest.newBuilder(); + builder.setMessage("hello world"); + return builder.build(); + } + + public EchoResponse buildResponse() { + + EchoResponse.Builder builder = EchoResponse.newBuilder(); + builder.setMessage("sync!"); + return builder.build(); + + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolTest.java new file mode 100644 index 00000000..a15b883d --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/BaiduRpcProtocolTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import java.lang.reflect.Constructor; +import java.util.Map; + +import com.baidu.brpc.RpcOptionsUtils; +import org.junit.Assert; +import org.junit.Test; + +import com.baidu.brpc.RpcMethodInfo; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.RpcRequest; +import com.baidu.brpc.utils.ByteBufUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class BaiduRpcProtocolTest { + @Test + public void testEncodeRequest() throws Exception { + RpcRequest rpcRequest = buildRpcRequest(); + Assert.assertTrue(rpcRequest != null); + ByteBuf buf = new BaiduRpcProtocol().encodeRequest(rpcRequest); + Assert.assertTrue(buf.readableBytes() > 0); + System.out.println(buf.readableBytes()); + System.out.println(ByteBufUtils.byteBufToString(buf)); + } + + @Test + public void testDecode() throws Exception { + RpcRequest rpcRequest = buildRpcRequest(); + ByteBuf buf = new BaiduRpcProtocol().encodeRequest(rpcRequest); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); + compositeByteBuf.addBuffer(buf); + Assert.assertTrue(buf.readableBytes() == compositeByteBuf.readableBytes()); + System.out.println(compositeByteBuf.toString()); + + BaiduRpcDecodePacket packet = new BaiduRpcProtocol().decode(null, compositeByteBuf, true); + Assert.assertTrue(packet.getMetaBuf().readableBytes() > 0); + System.out.println(packet.getMetaBuf()); + Assert.assertTrue(packet.getProtoAndAttachmentBuf().readableBytes() > 0); + System.out.println(packet.getProtoAndAttachmentBuf()); + } + + public RpcRequest buildRpcRequest() throws Exception { + RpcRequest rpcRequest = new RpcRequest(); + rpcRequest.setLogId(0); + rpcRequest.setServiceName(EchoService.class.getName()); + rpcRequest.setTargetMethod(EchoService.class.getMethod("echo", Echo.EchoRequest.class)); + rpcRequest.setMethodName(rpcRequest.getTargetMethod().getName()); + rpcRequest.setTarget(new EchoServiceImpl()); + rpcRequest.setRpcMethodInfo(buildRpcMethodInfo()); + + Echo.EchoRequest echoRequest = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + rpcRequest.setArgs(new Object[] {echoRequest}); + rpcRequest.setBinaryAttachment(Unpooled.wrappedBuffer("hello".getBytes())); + rpcRequest.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE_VALUE); + return rpcRequest; + } + + public static RpcMethodInfo buildRpcMethodInfo() throws Exception { + Class[] paramTypes = new Class[2]; + paramTypes[0] = RpcClient.class; + paramTypes[1] = Class.class; + Constructor constructor = BrpcProxy.class.getDeclaredConstructor(paramTypes); + constructor.setAccessible(true); + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8002", RpcOptionsUtils.getRpcClientOptions()); + BrpcProxy rpcProxy = (BrpcProxy) constructor.newInstance(rpcClient, EchoService.class); + rpcClient.shutdown(); + Map methodInfoMap = rpcProxy.getRpcMethodMap(); + RpcMethodInfo rpcMethodInfo = methodInfoMap.entrySet().iterator().next().getValue(); + return rpcMethodInfo; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoService.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoService.java new file mode 100644 index 00000000..bf74f46e --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoService.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import com.baidu.brpc.protocol.BrpcMeta; +import com.baidu.brpc.protocol.nshead.NSHeadMeta; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + @NSHeadMeta + Echo.EchoResponse echo(Echo.EchoRequest request); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceAsync.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceAsync.java new file mode 100644 index 00000000..d71915ee --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceAsync.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +import com.baidu.brpc.client.RpcCallback; +import java.util.concurrent.Future; + +/** + * Created by baidu on 2017/9/23. + */ +public interface EchoServiceAsync extends EchoService { + Future echo(Echo.EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceImpl.java b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceImpl.java new file mode 100644 index 00000000..9fbafe30 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/protocol/standard/EchoServiceImpl.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.protocol.standard; + +// import io.brpc.protocol.RpcContext; +// import io.netty.buffer.ByteBuf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public Echo.EchoResponse echo(Echo.EchoRequest request) { + // 读取request attachment +// RpcContext rpcContext = RpcContext.getContext(); +// String remoteHost = rpcContext.getRemoteHost(); +// LOG.debug("remote host:{}", remoteHost); +// ByteBuf attachment = rpcContext.getRequestBinaryAttachment(); +// if (attachment != null) { +// if (LOG.isDebugEnabled()) { +// String attachmentString = new String(attachment.array()); +// LOG.debug("request attachment={}", attachmentString); +// } + // 设置response attachment +// rpcContext.setResponseBinaryAttachment(Unpooled.copiedBuffer(attachment)); +// } + + String message = request.getMessage(); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage(message).build(); +// LOG.debug("EchoService.echo, request={}, response={}", +// request.getMessage(), response.getMessage()); + + return response; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/ServerPushTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/ServerPushTest.java new file mode 100644 index 00000000..0c5044ad --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/ServerPushTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.push; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.push.userservice.PushData; +import com.baidu.brpc.push.userservice.PushResult; +import com.baidu.brpc.push.userservice.ServerSideUserPushApi; +import com.baidu.brpc.push.userservice.UserPushApiImpl; +import com.baidu.brpc.server.BrpcPushProxy; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.server.ServiceManager; + +public class ServerPushTest { + + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + @Test + public void testBasic() { + RpcServerOptions rpcServerOptions = RpcOptionsUtils.getRpcServerOptions(); + rpcServerOptions.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + RpcServer rpcServer = new RpcServer(8000, rpcServerOptions); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + RpcClientOptions rpcClientOptions = RpcOptionsUtils.getRpcClientOptions(); + rpcClientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + rpcClientOptions.setClientName("c1"); + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000", rpcClientOptions); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + rpcClient.registerPushService(new UserPushApiImpl()); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + Echo.EchoResponse response = echoService.echo(request); + assertEquals("hello", response.getMessage()); + + ServerSideUserPushApi pushApi = + (ServerSideUserPushApi) BrpcPushProxy.getProxy(rpcServer, ServerSideUserPushApi.class); + PushData p = new PushData(); + p.setData("abc"); + PushResult pushResult = pushApi.clientReceive("c1", p); + + assertEquals("got data:abc", pushResult.getResult()); + + rpcClient.stop(); + + rpcServer.shutdown(); + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushData.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushData.java new file mode 100644 index 00000000..5458c3ef --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushData.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.push.userservice; + +public class PushData { + + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushResult.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushResult.java new file mode 100644 index 00000000..4a69516d --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/PushResult.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.push.userservice; + +public class PushResult { + + public String result; + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/ServerSideUserPushApi.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/ServerSideUserPushApi.java new file mode 100644 index 00000000..88946deb --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/ServerSideUserPushApi.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.push.userservice; + +public interface ServerSideUserPushApi extends UserPushApi { + + /** + * server端接口, 多一个clientName参数 + * + * @param clientName + * @param data + * + * @return + */ + PushResult clientReceive(String clientName, PushData data); + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApi.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApi.java new file mode 100644 index 00000000..c6a19d55 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApi.java @@ -0,0 +1,6 @@ +package com.baidu.brpc.push.userservice; + +public interface UserPushApi { + + PushResult clientReceive(PushData data); +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApiImpl.java b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApiImpl.java new file mode 100644 index 00000000..f5776387 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/push/userservice/UserPushApiImpl.java @@ -0,0 +1,12 @@ +package com.baidu.brpc.push.userservice; + +public class UserPushApiImpl implements UserPushApi { + + @Override + public PushResult clientReceive(PushData data) { + System.out.println("++invoke clientReceive :" + data.getData()); + PushResult pushResult = new PushResult(); + pushResult.setResult("got data:" + data.getData()); + return pushResult; + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/server/ServerInitTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/server/ServerInitTest.java new file mode 100644 index 00000000..5a2675e4 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/server/ServerInitTest.java @@ -0,0 +1,99 @@ +package com.baidu.brpc.server; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.Echo.EchoRequest; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.RpcOptionsUtils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ServerInitTest { + + @Test + public void testInitServerMultiTimes() throws Exception { + + RpcServer rpcServer1 = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer1.registerService(new EchoServiceImpl()); + rpcServer1.start(); + + RpcServer rpcServer2 = new RpcServer(8001, RpcOptionsUtils.getRpcServerOptions()); + rpcServer2.registerService(new EchoServiceImpl(), RpcOptionsUtils.getRpcServerOptions()); + rpcServer2.start(); + + RpcClient secondRpcClient = new RpcClient("list://127.0.0.1:8001", + RpcOptionsUtils.getRpcClientOptions()); + EchoService echoService = BrpcProxy.getProxy(secondRpcClient, EchoService.class); + EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + echoService.echo(request); + + int processor = Runtime.getRuntime().availableProcessors(); + ThreadNumStat stat1 = calThreadNum(); + Assert.assertEquals(2, stat1.serverWorkThreadNum); + Assert.assertEquals(1, stat1.customWorkThreadNum); + Assert.assertEquals(1, stat1.clientWorkThreadNum); + + rpcServer1.shutdown(); + rpcServer2.shutdown(); + Thread.sleep(3); + + ThreadNumStat stat2 = calThreadNum(); + Assert.assertEquals(0, stat2.serverIoThreadNum); + Assert.assertEquals(0, stat2.serverWorkThreadNum); + Assert.assertEquals(0, stat2.customWorkThreadNum); + secondRpcClient.shutdown(); + } + + private ThreadNumStat calThreadNum() { + ThreadNumStat stat = new ThreadNumStat(); + + // stat all thread + Map allThreadMap = Thread.getAllStackTraces(); + for (Map.Entry entry : allThreadMap.entrySet()) { + + Thread thread = entry.getKey(); + + if (thread.getName().contains("server-io-thread")) { + stat.serverIoThreadNum ++; + } else if (thread.getName().contains("server-work-thread")) { + stat.serverWorkThreadNum++; + } else if (thread.getName().contains("client-io-thread")) { + stat.clientIoThreadNum ++; + } else if (thread.getName().contains("client-work-thread")) { + stat.clientWorkThreadNum ++; + } else if (thread.getName().contains("server-acceptor-thread")) { + stat.acceptorThreadNum ++; + } else if (thread.getName().contains("EchoServiceImpl-work-thread")) { + stat.customWorkThreadNum ++; + } + } + + log.info("thread statistic data, serverIoThreadNum : {}, serverWorkThreadNum : {}, " + + "clientIoThreadNum : {}, clientWorkThreadNum : {}, acceptorThreadNum : {}, " + + "customizedWorkThreadNum : {}", + stat.serverIoThreadNum, stat.serverWorkThreadNum, + stat.clientIoThreadNum, stat.clientWorkThreadNum, + stat.acceptorThreadNum, stat.customWorkThreadNum); + + return stat; + } + + public static class ThreadNumStat { + public int serverIoThreadNum; + public int serverWorkThreadNum; + public int clientIoThreadNum; + public int clientWorkThreadNum; + public int acceptorThreadNum; + public int customWorkThreadNum; + } + + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/server/currentlimit/CurrentLimitTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/server/currentlimit/CurrentLimitTest.java new file mode 100644 index 00000000..72f9fac3 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/server/currentlimit/CurrentLimitTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.server.currentlimit; + +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.interceptor.CurrentLimitInterceptor; +import com.baidu.brpc.server.RpcServer; + +public class CurrentLimitTest { + + private static RpcServer rpcServer1; + + private static RpcServer rpcServer2; + + @BeforeClass + public static void beforeClass() { + rpcServer1 = new RpcServer(8000, RpcOptionsUtils.getRpcServerOptions()); + rpcServer1.registerService(new EchoServiceImpl()); + rpcServer1.getInterceptors().add(new CurrentLimitInterceptor(new TokenBucketCurrentLimiter(500, 500))); + + rpcServer2 = new RpcServer(8001, RpcOptionsUtils.getRpcServerOptions()); + rpcServer2.registerService(new EchoServiceImpl()); + rpcServer2.getInterceptors().add(new CurrentLimitInterceptor(new CounterCurrentLimiter(500))); + + rpcServer1.start(); + rpcServer2.start(); + } + + @AfterClass + public static void afterClass() { + if (rpcServer1 != null) { + rpcServer1.shutdown(); + } + if (rpcServer2 != null) { + rpcServer2.shutdown(); + } + } + + @Test + public void test1Client2Server() { + RpcClient rpcClient = new RpcClient("list://127.0.0.1:8000,127.0.0.1:8001", + RpcOptionsUtils.getRpcClientOptions()); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + for (int i = 0; i < 100; i++) { + echoService.echo(request); + } + rpcClient.stop(); + } + +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/test/BaseMockitoTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/test/BaseMockitoTest.java new file mode 100644 index 00000000..97ff464f --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/test/BaseMockitoTest.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.test; + +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public abstract class BaseMockitoTest { +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/thread/GlobalThreadPoolSharingTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/thread/GlobalThreadPoolSharingTest.java new file mode 100644 index 00000000..9e5ab81d --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/thread/GlobalThreadPoolSharingTest.java @@ -0,0 +1,118 @@ +package com.baidu.brpc.thread; + +import static org.junit.Assert.assertEquals; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.baidu.brpc.RpcOptionsUtils; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.baidu.brpc.protocol.standard.EchoServiceImpl; +import com.baidu.brpc.push.userservice.UserPushApiImpl; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.server.ServiceManager; +import com.baidu.brpc.utils.ThreadPool; + +import io.netty.channel.EventLoopGroup; + +public class GlobalThreadPoolSharingTest { + + @Before + public void init() { + if (ServiceManager.getInstance() != null) { + ServiceManager.getInstance().getServiceMap().clear(); + } + } + + @Test + @Ignore + public void testShareGlobalThreadPool() { + RpcServerOptions rpcServerOptions = RpcOptionsUtils.getRpcServerOptions(); + rpcServerOptions.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + rpcServerOptions.setGlobalThreadPoolSharing(true); + RpcServer rpcServer1 = new RpcServer(8000, rpcServerOptions); + rpcServer1.registerService(new EchoServiceImpl()); + rpcServer1.start(); + RpcServer rpcServer2 = new RpcServer(8001, rpcServerOptions); + rpcServer2.registerService(new EchoServiceImpl()); + rpcServer2.start(); + Assert.assertTrue(rpcServer1.getBossGroup() == rpcServer2.getBossGroup()); + Assert.assertTrue(rpcServer1.getWorkerGroup() == rpcServer2.getWorkerGroup()); + Assert.assertTrue(rpcServer1.getThreadPool() == rpcServer2.getThreadPool()); + + RpcClientOptions rpcClientOptions = RpcOptionsUtils.getRpcClientOptions(); + rpcClientOptions.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + rpcClientOptions.setClientName("c1"); + rpcClientOptions.setGlobalThreadPoolSharing(true); + + RpcClient rpcClient1 = new RpcClient("list://127.0.0.1:8000", rpcClientOptions); + EchoService echoService1 = BrpcProxy.getProxy(rpcClient1, EchoService.class); + rpcClient1.registerPushService(new UserPushApiImpl()); + RpcClient rpcClient2 = new RpcClient("list://127.0.0.1:8001", rpcClientOptions); + EchoService echoService2 = BrpcProxy.getProxy(rpcClient2, EchoService.class); + rpcClient2.registerPushService(new UserPushApiImpl()); + RpcClient rpcClient3 = new RpcClient("list://127.0.0.1:8001", rpcClientOptions); + EchoService echoService3 = BrpcProxy.getProxy(rpcClient3, EchoService.class); + rpcClient3.registerPushService(new UserPushApiImpl()); + Assert.assertTrue(rpcClient1.getWorkThreadPool() == rpcClient2.getWorkThreadPool()); + Assert.assertTrue(rpcClient1.getIoThreadPool() == rpcClient2.getIoThreadPool()); + Assert.assertTrue(rpcClient1.getWorkThreadPool() == rpcClient3.getWorkThreadPool()); + Assert.assertTrue(rpcClient1.getIoThreadPool() == rpcClient3.getIoThreadPool()); + + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + for (int i = 0; i < 1000; i++) { + Echo.EchoResponse response = echoService1.echo(request); + Echo.EchoResponse response2 = echoService2.echo(request); + Echo.EchoResponse response3 = echoService3.echo(request); + assertEquals("hello", response.getMessage()); + assertEquals("hello", response2.getMessage()); + assertEquals("hello", response3.getMessage()); + } + + // test shutndown and stop + + rpcClient1.stop(); + rpcClient2.stop(); + rpcClient3.stop(); + rpcServer1.shutdown(); + rpcServer2.shutdown(); + // client + ThreadPool workThreadPool = rpcClient1.getWorkThreadPool(); + EventLoopGroup ioThreadPool = rpcClient1.getIoThreadPool(); + Assert.assertFalse(workThreadPool.isStopped()); + Assert.assertFalse(ioThreadPool.isShutdown()); + + // server + EventLoopGroup r1BossGroup = rpcServer1.getBossGroup(); + EventLoopGroup r1WorkerGroup = rpcServer1.getWorkerGroup(); + ThreadPool r1ThreadPool = rpcServer1.getThreadPool(); + + Assert.assertFalse(r1BossGroup.isShutdown()); + Assert.assertFalse(r1WorkerGroup.isShutdown()); + Assert.assertFalse(r1ThreadPool.isStopped()); + + ShutDownManager.shutdownGlobalThreadPools(); + + try { + Thread.sleep(5 * 1000L); + } catch (InterruptedException e) { + // do nothing + } + + Assert.assertTrue(workThreadPool.isStopped()); + Assert.assertTrue(ioThreadPool.isShutdown()); + + Assert.assertTrue(r1BossGroup.isShutdown()); + Assert.assertTrue(r1WorkerGroup.isShutdown()); + Assert.assertTrue(r1ThreadPool.isStopped()); + + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/ByteBufUtils.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ByteBufUtils.java new file mode 100644 index 00000000..a9a91c1d --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ByteBufUtils.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import io.netty.buffer.ByteBuf; + +public class ByteBufUtils { + public static String byteBufToString(ByteBuf buf) { + StringBuilder sb = new StringBuilder(); + if (buf.readableBytes() == 0) { + return sb.toString(); + } + for (int i = buf.readerIndex(); i < buf.readerIndex() + buf.readableBytes(); i++) { + sb.append(buf.getUnsignedByte(i)).append(" "); + } + return sb.toString(); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/GsonUtilsTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/GsonUtilsTest.java new file mode 100644 index 00000000..a2eeddaf --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/GsonUtilsTest.java @@ -0,0 +1,28 @@ +package com.baidu.brpc.utils; + + +import java.util.Date; + +import org.junit.Assert; +import org.junit.Test; + +import com.google.gson.reflect.TypeToken; + +public class GsonUtilsTest { + + @Test + public void fromJson() { + Date date = new Date(); + Date d1 = GsonUtils.fromJson(GsonUtils.toJson(date), new TypeToken(){}.getType()); + Date d2 = GsonUtils.fromJson(GsonUtils.toJson(date), new TypeToken(){}.getType()); + + date = new java.sql.Date(System.currentTimeMillis()); + d1 = GsonUtils.fromJson(GsonUtils.toJson(date), new TypeToken(){}.getType()); + d2 = GsonUtils.fromJson(GsonUtils.toJson(date), new TypeToken(){}.getType()); + + java.sql.Date sDate = new java.sql.Date(System.currentTimeMillis()); + java.sql.Date d3 = GsonUtils.fromJson(GsonUtils.toJson(date), new TypeToken(){}.getType()); + + + } +} \ No newline at end of file diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/IOUtilsTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/IOUtilsTest.java new file mode 100644 index 00000000..3f1e9058 --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/IOUtilsTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.Unpooled; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class IOUtilsTest { + + @Test + public void testByteBufToString() throws IOException { + ByteBuf byteBuf = Unpooled.buffer(16); + byteBuf.writeInt(123); + byteBuf.writeInt(456); + ByteBufInputStream inputStream = new ByteBufInputStream(byteBuf); + byte[] bytes = IOUtils.readInputStream(inputStream); + Assert.assertEquals(8, bytes.length); + + ByteBuffer buf = ByteBuffer.wrap(bytes); + Assert.assertEquals(123, buf.getInt(0)); + Assert.assertEquals(456, buf.getInt(4)); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/ProtobufUtilsTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ProtobufUtilsTest.java new file mode 100644 index 00000000..8212f7ef --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ProtobufUtilsTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import com.baidu.brpc.protocol.jprotobuf.EchoRequest; +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import com.google.protobuf.Message; +import com.baidu.brpc.buffer.DynamicCompositeByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.Unpooled; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; + +public class ProtobufUtilsTest { + @Test + public void testGetMessageType() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + ProtobufUtils.MessageType messageType = ProtobufUtils.getMessageType(method); + Assert.assertTrue(messageType == ProtobufUtils.MessageType.PROTOBUF); + + Method method2 = com.baidu.brpc.protocol.jprotobuf.EchoService.class.getMethod("echo", EchoRequest.class); + ProtobufUtils.MessageType messageType2 = ProtobufUtils.getMessageType(method2); + Assert.assertTrue(messageType2 == ProtobufUtils.MessageType.JPROTOBUF); + } + + @Test + public void testParseFrom() { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + Echo.EchoRequest request1 = (Echo.EchoRequest) ProtobufUtils.parseFrom(bytes, request.getClass()); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testParseFrom2() { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + InputStream inputStream = new ByteBufInputStream(Unpooled.wrappedBuffer(bytes)); + Echo.EchoRequest request1 = (Echo.EchoRequest) ProtobufUtils.parseFrom(inputStream, request.getClass()); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testParseFrom3() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + Message defaultInstance = request.getDefaultInstanceForType(); + Echo.EchoRequest request1 = (Echo.EchoRequest) ProtobufUtils.parseFrom(buf, defaultInstance); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } + + @Test + public void testParseFrom4() throws IOException { + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + byte[] bytes = request.toByteArray(); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(buf); + Message defaultInstance = request.getDefaultInstanceForType(); + Echo.EchoRequest request1 = (Echo.EchoRequest) ProtobufUtils.parseFrom(compositeByteBuf, defaultInstance); + Assert.assertTrue(request1.getMessage().equals(request.getMessage())); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/RpcMetaUtilsTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/RpcMetaUtilsTest.java new file mode 100644 index 00000000..d273229b --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/RpcMetaUtilsTest.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import com.baidu.brpc.protocol.standard.Echo; +import com.baidu.brpc.protocol.standard.EchoService; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Method; + +public class RpcMetaUtilsTest { + @Test + public void testParseRpcMeta() throws Exception { + Method method = EchoService.class.getMethod("echo", Echo.EchoRequest.class); + RpcMetaUtils.RpcMetaInfo rpcMeta = RpcMetaUtils.parseRpcMeta(method); + Assert.assertTrue(rpcMeta.getServiceName().equals("example.EchoService")); + Assert.assertTrue(rpcMeta.getMethodName().equals("Echo")); + } +} diff --git a/brpc-java-core/src/test/java/com/baidu/brpc/utils/ThreadPoolTest.java b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ThreadPoolTest.java new file mode 100644 index 00000000..a07583df --- /dev/null +++ b/brpc-java-core/src/test/java/com/baidu/brpc/utils/ThreadPoolTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.utils; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicInteger; + +public class ThreadPoolTest { + @Before + public void setup() { + + } + + @After + public void teardown() { + + } + + @Test + public void sanity() { + ThreadPool threadPool = new ThreadPool(2, new CustomThreadFactory("test")); + for (int i = 0; i < 100; ++i) { + threadPool.submit(new Runnable() { + @Override + public void run() { + System.out.println("I was run"); + } + }); + } + System.out.println("here"); + threadPool.stop(); + threadPool.join(); + } + + @Test + public void fifo() { + // Only one consumer thread + ThreadPool threadPool = new ThreadPool(1, new CustomThreadFactory("test")); + final AtomicInteger numConsumed = new AtomicInteger(0); + final AtomicInteger numCreated = new AtomicInteger(0); + for (int i = 0; i < 100; ++i) { + threadPool.submit(new Runnable() { + int index = numCreated.getAndAdd(1); + + @Override + public void run() { + Assert.assertEquals(numConsumed.getAndAdd(1), index); + } + }); + } + threadPool.stop(); + threadPool.join(); + } + +} diff --git a/brpc-java-core/src/test/proto/echo.proto b/brpc-java-core/src/test/proto/echo.proto new file mode 100644 index 00000000..c443f970 --- /dev/null +++ b/brpc-java-core/src/test/proto/echo.proto @@ -0,0 +1,18 @@ +syntax="proto2"; + +package example_for_cpp; +option java_package="com.baidu.brpc.protocol.standard"; +option java_outer_classname="Echo"; +option cc_generic_services = true; + +message EchoRequest { + required string message = 1; +}; + +message EchoResponse { + required string message = 1; +}; + +service EchoService { + rpc Echo(EchoRequest) returns (EchoResponse); +}; diff --git a/brpc-java-core/src/test/resources/log4j2.xml b/brpc-java-core/src/test/resources/log4j2.xml new file mode 100644 index 00000000..0090d8ca --- /dev/null +++ b/brpc-java-core/src/test/resources/log4j2.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + %d %p [%t]\t%m%n + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/brpc-java-core/src/test/resources/message.txt b/brpc-java-core/src/test/resources/message.txt new file mode 100644 index 00000000..b6fc4c62 --- /dev/null +++ b/brpc-java-core/src/test/resources/message.txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/brpc-java-core/src/test/resources/message_1k.txt b/brpc-java-core/src/test/resources/message_1k.txt new file mode 100644 index 00000000..8bfcfc8a --- /dev/null +++ b/brpc-java-core/src/test/resources/message_1k.txt @@ -0,0 +1,20 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-core/src/test/resources/message_2k.txt b/brpc-java-core/src/test/resources/message_2k.txt new file mode 100644 index 00000000..373c659d --- /dev/null +++ b/brpc-java-core/src/test/resources/message_2k.txt @@ -0,0 +1,40 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-core/src/test/resources/message_4k.txt b/brpc-java-core/src/test/resources/message_4k.txt new file mode 100644 index 00000000..eb9e1ba0 --- /dev/null +++ b/brpc-java-core/src/test/resources/message_4k.txt @@ -0,0 +1,80 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-core/src/test/resources/server_list.conf b/brpc-java-core/src/test/resources/server_list.conf new file mode 100644 index 00000000..fa7b63f5 --- /dev/null +++ b/brpc-java-core/src/test/resources/server_list.conf @@ -0,0 +1 @@ +127.0.0.1:8002 diff --git a/brpc-java-core/src/test/resources/test_server_list.txt b/brpc-java-core/src/test/resources/test_server_list.txt new file mode 100644 index 00000000..4fc894a2 --- /dev/null +++ b/brpc-java-core/src/test/resources/test_server_list.txt @@ -0,0 +1,2 @@ +127.0.0.1:8002 +invalid will skip diff --git a/brpc-java-examples/brpc-java-core-examples/pom.xml b/brpc-java-examples/brpc-java-core-examples/pom.xml new file mode 100644 index 00000000..b6b7797c --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/pom.xml @@ -0,0 +1,126 @@ + + + + 4.0.0 + + + com.baidu + brpc-java-examples + 2.5.9 + + + brpc-java-core-examples + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + release + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/dependency + false + false + compile + true + + + + + + + + + + + com.baidu + brpc-java + + + com.baidu + brpc-spring + + + com.baidu + brpc-java-naming-zookeeper + + + com.baidu + brpc-java-naming-consul + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_client.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_client.sh new file mode 100755 index 00000000..d3aa4059 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_client.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +if [[ $# != 2 ]]; then + printf "Usage:\n" + printf "\tsh run_client.sh \n" + printf "Sample:\n" + printf "\tsh run_client.sh list://127.0.0.1:8002 8\n" + exit 1 +fi + +ADDRESS=$1 +THREAD_NUM=$2 + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/client_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.standard.BenchmarkTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} ${ADDRESS} ${THREAD_NUM} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_client.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_client.sh new file mode 100755 index 00000000..2662a285 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_client.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +if [[ $# != 2 ]]; then + printf "Usage:\n" + printf "\tsh run_http_client.sh \n" + printf "Sample:\n" + printf "\tsh run_http_client.sh list://127.0.0.1:8080 8\n" + exit 1 +fi + +ADDRESS=$1 +THREAD_NUM=$2 + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/http_client_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.http.BenchmarkTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} ${ADDRESS} ${THREAD_NUM} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_server.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_server.sh new file mode 100755 index 00000000..2d22e1a9 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_http_server.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/http_server_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.http.proto.RpcServerTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_client.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_client.sh new file mode 100755 index 00000000..887fa9ca --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_client.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +if [[ $# != 2 ]]; then + printf "Usage:\n" + printf "\tsh run_jprotobuf_client.sh \n" + printf "Sample:\n" + printf "\tsh run_jprotobuf_client.sh list://127.0.0.1:8002 8\n" + exit 1 +fi + +ADDRESS=$1 +THREAD_NUM=$2 + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/jprotobuf_client_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.jprotobuf.BenchmarkTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} ${ADDRESS} ${THREAD_NUM} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_server.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_server.sh new file mode 100644 index 00000000..ccc1e295 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_jprotobuf_server.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +export JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/server_gc.log " + +export CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +export MAIN_CLASS="com.baidu.brpc.example.jprotobuf.RpcServerTest" + +java $JVM_OPTIONS -cp $CUSTOM_CLASSPATH $MAIN_CLASS diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_client.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_client.sh new file mode 100755 index 00000000..874d4857 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_client.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +if [[ $# != 2 ]]; then + printf "Usage:\n" + printf "\tsh run_client.sh \n" + printf "Sample:\n" + printf "\tsh run_client.sh list://127.0.0.1:8002 8\n" + exit 1 +fi + +ADDRESS=$1 +THREAD_NUM=$2 + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/client_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.push.BenchmarkClientPushTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} ${ADDRESS} ${THREAD_NUM} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_server.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_server.sh new file mode 100644 index 00000000..c84d99d0 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_push_server.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +THREAD_NUM=$1 + +export JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/server_gc.log " + +export CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +export MAIN_CLASS="com.baidu.brpc.example.push.BenchmarkServerPushTest" + +java $JVM_OPTIONS -cp $CUSTOM_CLASSPATH $MAIN_CLASS $THREAD_NUM diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_server.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_server.sh new file mode 100644 index 00000000..bce89b3a --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_server.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +export JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/server_gc.log " + +export CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +export MAIN_CLASS="com.baidu.brpc.example.standard.RpcServerTest" + +java $JVM_OPTIONS -cp $CUSTOM_CLASSPATH $MAIN_CLASS diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_sync_client.sh b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_sync_client.sh new file mode 100755 index 00000000..9276857d --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/bin/run_sync_client.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +cd `dirname $0` +PROJECT_DIR=`pwd`/../../../ +cd ${PROJECT_DIR} + +if [[ $# != 2 ]]; then + printf "Usage:\n" + printf "\tsh run_sync_client.sh \n" + printf "Sample:\n" + printf "\tsh run_sync_client.sh list://127.0.0.1:8002 8\n" + exit 1 +fi + +ADDRESS=$1 +THREAD_NUM=$2 + +LOG_DIR="./logs" +if [[ ! -d ${LOG_DIR} ]];then + mkdir ${LOG_DIR} +fi + +JVM_OPTIONS=" -server -Xmn2g -Xmx6g -Xms6g -Xss256k -Xverify:none \ + -XX:+DisableExplicitGC -XX:+AlwaysPreTouch \ + -XX:+AggressiveOpts -XX:AutoBoxCacheMax=20000 \ + -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \ + -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 \ + -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/sync_client_gc.log " + +CUSTOM_CLASSPATH="target/classes:target/test-classes:target/dependency/* " + +MAIN_CLASS="com.baidu.brpc.example.standard.SyncBenchmarkTest" + +java ${JVM_OPTIONS} -cp ${CUSTOM_CLASSPATH} ${MAIN_CLASS} ${ADDRESS} ${THREAD_NUM} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/BenchmarkTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/BenchmarkTest.java new file mode 100644 index 00000000..be6a00ed --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/BenchmarkTest.java @@ -0,0 +1,125 @@ +package com.baidu.brpc.example.http; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.standard.Echo; +import com.baidu.brpc.example.standard.Echo.EchoRequest; +import com.baidu.brpc.example.standard.Echo.EchoResponse; +import com.baidu.brpc.example.standard.EchoServiceAsync; +import com.baidu.brpc.protocol.Options.ProtocolType; + +public class BenchmarkTest { + + private static volatile int successRequestNum = 0; + private static volatile int failRequestNum = 0; + private static volatile long totalElapsedNs = 0; + private static volatile boolean stop = false; + + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("usage: BenchmarkTest list://127.0.0.1:8080 threadNum"); + System.exit(-1); + } + RpcClientOptions options = new RpcClientOptions(); + options.setProtocolType(ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + options.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + options.setMaxTotalConnections(1000000); + options.setMinIdleConnections(10); + options.setReadTimeoutMillis(5000); + options.setConnectTimeoutMillis(1000); + RpcClient rpcClient = new RpcClient(args[0], options, null); + EchoServiceAsync echoServiceAsync = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + int threadNum = Integer.parseInt(args[1]); + Thread[] threads = new Thread[threadNum]; + for (int i = 0; i < threadNum; i++) { + threads[i] = new Thread(new ThreadTask(echoServiceAsync), "work-thread-" + i); + threads[i].start(); + } + Thread qpsThread = new Thread(new Runnable() { + @Override + public void run() { + while (!stop) { + int lastSuccessRequestNum = successRequestNum; + int lastFailRequestNum = failRequestNum; + long lastElapsedNs = totalElapsedNs; + try { + Thread.sleep(1000); + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + int successNum = successRequestNum - lastSuccessRequestNum; + int failNum = failRequestNum - lastFailRequestNum; + long averageElapsedNs = 0; + if (successNum > 0) { + averageElapsedNs = (totalElapsedNs - lastElapsedNs) / successNum; + } + System.out.printf("success=%d,fail=%d,average=%dns\n", + successNum, failNum, averageElapsedNs); + } + } + }, "stat-qps-thread"); + qpsThread.start(); + + for (int i = 0; i < threadNum; i++) { + try { + threads[i].join(); + } catch (InterruptedException ex) { + // ignore + } + + } + } + + public static class EchoCallback implements RpcCallback { + private long startTime; + + public EchoCallback(long startTime) { + this.startTime = startTime; + } + + @Override + public void success(EchoResponse response) { + if (response != null) { + successRequestNum++; + long elapseTimeNs = System.nanoTime() - startTime; + totalElapsedNs += elapseTimeNs; +// System.out.printf("async call success, elapseTimeNs=%d, response=%s\n", +// System.nanoTime() - startTime, response.getMessage()); + } else { + failRequestNum++; +// System.out.println("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + failRequestNum++; +// System.out.printf("async call failed, %s\n", e.getMessage()); + } + } + + public static class ThreadTask implements Runnable { + + private EchoServiceAsync echoServiceAsync; + + public ThreadTask(EchoServiceAsync echoServiceAsync) { + this.echoServiceAsync = echoServiceAsync; + } + + public void run() { + while (!stop) { + try { + // build request + EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello").build(); + echoServiceAsync.echo(request, new EchoCallback(System.nanoTime())); + } catch (Exception ex) { + System.out.println("send exception:" + ex.getMessage()); + } + } + } + + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/ShortConnectionRpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/ShortConnectionRpcClientTest.java new file mode 100644 index 00000000..e815c864 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/ShortConnectionRpcClientTest.java @@ -0,0 +1,84 @@ +package com.baidu.brpc.example.http; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.http.json.EchoService; +import com.baidu.brpc.example.http.json.EchoServiceAsync; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options.ProtocolType; +import com.google.gson.Gson; + +public class ShortConnectionRpcClientTest { + + public static void main(String[] args) { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(ProtocolType.PROTOCOL_HTTP_JSON_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(5000); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setMaxTryTimes(1); + clientOption.setChannelType(ChannelType.SHORT_CONNECTION); + + String serviceUrl = "list://127.0.0.1:8080"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + List interceptors = new ArrayList();; + interceptors.add(new CustomInterceptor()); + + // sync call + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + try { + String response = echoService.hello("okok"); + System.out.printf("sync call success, response=%s\n", response); + } catch (RpcException ex) { + System.out.println("sync call failed, msg=" + ex.getMessage()); + } + rpcClient.stop(); + + // async call + rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + RpcCallback callback = new RpcCallback() { + @Override + public void success(String response) { + if (response != null) { + System.out.printf("async call success, response=%s\n", + new Gson().toJson(response)); + } else { + System.out.println("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call failed, %s\n", e.getMessage()); + } + }; + EchoServiceAsync echoServiceAsync = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + try { + Future future = echoServiceAsync.hello("ok", callback); + try { + if (future != null) { + future.get(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (RpcException ex) { + System.out.println("send exception, ex=" + ex.getMessage()); + } + rpcClient.stop(); + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoService.java new file mode 100644 index 00000000..1e5fe6e6 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoService.java @@ -0,0 +1,6 @@ +package com.baidu.brpc.example.http.json; + +public interface EchoService { + String hello(String request); + String hello2(String userName, Integer userId); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceAsync.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceAsync.java new file mode 100644 index 00000000..0a1e6339 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceAsync.java @@ -0,0 +1,10 @@ +package com.baidu.brpc.example.http.json; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +public interface EchoServiceAsync extends EchoService { + Future hello(String request, RpcCallback callback); + Future hello2(String userName, Integer userId, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceImpl.java new file mode 100644 index 00000000..98f86102 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/EchoServiceImpl.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.example.http.json; + +public class EchoServiceImpl implements EchoService { + + @Override + public String hello(String request) { +// throw new RuntimeException("failed"); + return "hello " + request; + } + + @Override + public String hello2(String userName, Integer userId) { + return "userName=" + userName + ", userId=" + userId; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcClientTest.java new file mode 100644 index 00000000..1de9a13e --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcClientTest.java @@ -0,0 +1,85 @@ +package com.baidu.brpc.example.http.json; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options.ProtocolType; +import com.google.gson.Gson; + +public class RpcClientTest { + public static void main(String[] args) { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(ProtocolType.PROTOCOL_HTTP_JSON_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(30000); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setMaxTryTimes(1); + + String serviceUrl = "list://127.0.0.1:8080"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + List interceptors = new ArrayList();; + interceptors.add(new CustomInterceptor()); + + // sync call + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + try { + String response = echoService.hello("okok"); + System.out.printf("sync call hello success, response=%s\n", response); + + response = echoService.hello2("jack", 123); + System.out.printf("sync call hello2 success, response=%s\n", response); + } catch (RpcException ex) { + System.out.println("sync call failed, msg=" + ex.getMessage()); + } + rpcClient.stop(); + + // async call + rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + RpcCallback callback = new RpcCallback() { + @Override + public void success(String response) { + if (response != null) { + System.out.printf("async call success, response=%s\n", response); + } else { + System.out.println("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call failed, %s\n", e.getMessage()); + } + }; + EchoServiceAsync echoServiceAsync = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + try { + Future future = echoServiceAsync.hello("ok", callback); + Future future2 = echoServiceAsync.hello2("peter", 234, callback); + try { + if (future != null) { + future.get(); + } + if (future2 != null) { + future2.get(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (RpcException ex) { + System.out.println("send exception, ex=" + ex.getMessage()); + } + rpcClient.stop(); + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcServerTest.java new file mode 100644 index 00000000..003d2e2e --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/json/RpcServerTest.java @@ -0,0 +1,29 @@ +package com.baidu.brpc.example.http.json; + +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +public class RpcServerTest { + + public static void main(String[] args) { + int port = 8080; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + RpcServer rpcServer = new RpcServer(port, options); + // rpcServer.registerService(new EchoServiceImpl()); + rpcServer.registerService(new EchoServiceImpl(), options); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + // ignore + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcClientTest.java new file mode 100644 index 00000000..6f2d9324 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcClientTest.java @@ -0,0 +1,98 @@ +package com.baidu.brpc.example.http.proto; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.example.standard.Echo; +import com.baidu.brpc.example.standard.Echo.EchoRequest; +import com.baidu.brpc.example.standard.Echo.EchoResponse; +import com.baidu.brpc.example.standard.EchoService; +import com.baidu.brpc.example.standard.EchoServiceAsync; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options.ProtocolType; + +public class RpcClientTest { + + public static void main(String[] args) { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(ProtocolType.PROTOCOL_HTTP_PROTOBUF_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(500); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setMaxTryTimes(1); + + String serviceUrl = "list://127.0.0.1:8080"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + List interceptors = new ArrayList();; + interceptors.add(new CustomInterceptor()); + + // sync call + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + String message = + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + + "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello"; + EchoRequest request = Echo.EchoRequest.newBuilder().setMessage(message) + .build(); + try { + EchoResponse response = echoService.echo(request); + System.out.printf("sync call success, response=%s\n", response.getMessage()); + } catch (RpcException ex) { + System.out.println("sync call failed, msg=" + ex.getMessage()); + } + rpcClient.stop(); + + // async call + rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + RpcCallback callback = new RpcCallback() { + @Override + public void success(EchoResponse response) { + if (response != null) { + System.out.printf("async call success, response=%s\n", response.getMessage()); + } else { + System.out.println("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call failed, %s\n", e.getMessage()); + } + }; + EchoServiceAsync echoServiceAsync = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + request = Echo.EchoRequest.newBuilder().setMessage("hello world async").build(); + try { + Future future = echoServiceAsync.echo(request, callback); + try { + if (future != null) { + future.get(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (RpcException ex) { + System.out.println("send exception, ex=" + ex.getMessage()); + } + rpcClient.stop(); + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcServerTest.java new file mode 100644 index 00000000..14d05e69 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcServerTest.java @@ -0,0 +1,29 @@ +package com.baidu.brpc.example.http.proto; + +import com.baidu.brpc.example.standard.EchoServiceImpl; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +public class RpcServerTest { + + public static void main(String[] args) { + int port = 8080; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + // ignore + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/interceptor/CustomInterceptor.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/interceptor/CustomInterceptor.java new file mode 100644 index 00000000..98caf572 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/interceptor/CustomInterceptor.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.interceptor; + +import com.baidu.brpc.interceptor.AbstractInterceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +public class CustomInterceptor extends AbstractInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(CustomInterceptor.class); + + public boolean handleRequest(Request rpcRequest) { + LOG.info("request intercepted, correlationId={}, service={}, method={}", + rpcRequest.getCorrelationId(), + rpcRequest.getTarget().getClass().getSimpleName(), + rpcRequest.getTargetMethod().getName()); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + LOG.info("around intercepted, before proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + + // invoke the interceptor list + chain.intercept(request, response); + + LOG.info("around intercepted, after proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + } + + public void handleResponse(Response response) { + if (response != null) { + LOG.info("reponse intercepted, correlationId={}, result={}", + response.getCorrelationId(), response.getResult()); + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/BenchmarkTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/BenchmarkTest.java new file mode 100644 index 00000000..ffe02819 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/BenchmarkTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import java.io.IOException; +import java.io.InputStream; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.protocol.Options; + +import lombok.extern.slf4j.Slf4j; + +/** + * Created by wenweihu86 on 2017/5/1. + */ +@Slf4j +public class BenchmarkTest { + public static class SendInfo { + public long successRequestNum = 0; + public long failRequestNum = 0; + public long elapsedNs = 0; + } + + private static volatile boolean stop = false; + + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("usage: BenchmarkTest 127.0.0.1:8002 threadNum"); + System.exit(-1); + } + RpcClientOptions options = new RpcClientOptions(); + options.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + options.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + options.setMaxTotalConnections(1000000); + options.setMinIdleConnections(10); + options.setConnectTimeoutMillis(1000); + options.setWriteTimeoutMillis(1000); + options.setReadTimeoutMillis(5000); + options.setTcpNoDelay(false); + options.setChannelType(ChannelType.SINGLE_CONNECTION); +// options.setWorkThreadNum(2); + // options.setFutureBufferSize(10000); + RpcClient rpcClient = new RpcClient(args[0], options, null); + EchoServiceAsync echoService = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + int threadNum = Integer.parseInt(args[1]); + + byte[] messageBytes = null; + try { + InputStream inputStream = Thread.currentThread().getClass() + .getResourceAsStream("/message_1k.txt"); + int length = inputStream.available(); + messageBytes = new byte[length]; + inputStream.read(messageBytes); + log.info("message size=" + messageBytes.length); + } catch (IOException ex) { + System.exit(1); + } + + + SendInfo[] sendInfos = new SendInfo[threadNum]; + Thread[] threads = new Thread[threadNum]; + for (int i = 0; i < threadNum; i++) { + sendInfos[i] = new SendInfo(); + threads[i] = new Thread(new ThreadTask(rpcClient, echoService, messageBytes, sendInfos[i]), + "work-thread-" + i); + threads[i].start(); + } + + long lastSuccessRequestNum = 0; + long lastFailRequestNum = 0; + long lastElapsedNs = 0; + int second = 0; + long skippedQps = 0; + while (!stop) { + long beginTime = System.nanoTime(); + try { + Thread.sleep(1000); + ++second; + + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + + long successNum = 0; + long failNum = 0; + long elapseNs = 0; + long averageElapsedNs = 0; + for (SendInfo sendInfo : sendInfos) { + successNum += sendInfo.successRequestNum; + failNum += sendInfo.failRequestNum; + elapseNs += sendInfo.elapsedNs; + } + if (successNum - lastSuccessRequestNum > 0) { + averageElapsedNs = (elapseNs - lastElapsedNs) / (successNum - lastSuccessRequestNum); + } + long endTime = System.nanoTime(); + + String msg = String.format("success=%s,fail=%s,average=%sns", + (successNum - lastSuccessRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + (failNum - lastFailRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + averageElapsedNs); + + lastSuccessRequestNum = successNum; + lastFailRequestNum = failNum; + lastElapsedNs = elapseNs; + + // 从第10开始计算平均qps + if (second > 30) { + long avgQps = (lastSuccessRequestNum - skippedQps) / (second - 30); + msg = msg + ", avgQps=" + avgQps; + } else { + skippedQps = lastSuccessRequestNum; + } + + log.info(msg); + + } + } + + public static class EchoCallback implements RpcCallback { + private long startTime; + private SendInfo sendInfo; + + public EchoCallback(long startTime, SendInfo sendInfo) { + this.startTime = startTime; + this.sendInfo = sendInfo; + } + + @Override + public void success(EchoResponse response) { + if (response != null) { + sendInfo.successRequestNum++; + long elapseTimeNs = System.nanoTime() - startTime; + sendInfo.elapsedNs += elapseTimeNs; + log.debug("async call success, elapseTimeNs={}, response={}", + System.nanoTime() - startTime, response.getMessage()); + } else { + sendInfo.failRequestNum++; + log.debug("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + sendInfo.failRequestNum++; + log.debug("async call failed, {}", e.getMessage()); + } + } + + public static class ThreadTask implements Runnable { + + private RpcClient rpcClient; + EchoServiceAsync echoService; + private byte[] messageBytes; + private SendInfo sendInfo; + + public ThreadTask(RpcClient rpcClient, EchoServiceAsync echoService, + byte[] messageBytes, SendInfo sendInfo) { + this.rpcClient = rpcClient; + this.echoService = echoService; + this.messageBytes = messageBytes; + this.sendInfo = sendInfo; + } + + public void run() { + // build request + EchoRequest request = new EchoRequest(); + request.setMessage(new String(messageBytes)); +// byte[] attachment = "hello".getBytes(); + while (!stop) { + try { + echoService.echo(request, new EchoCallback(System.nanoTime(), sendInfo)); + } catch (Exception ex) { + log.info("send exception:" + ex.getMessage()); + sendInfo.failRequestNum++; + } + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoRequest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoRequest.java new file mode 100644 index 00000000..a933b50c --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoResponse.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoResponse.java new file mode 100644 index 00000000..bcde17eb --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoService.java new file mode 100644 index 00000000..ea190668 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceAsync.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceAsync.java new file mode 100644 index 00000000..aacc9592 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceAsync.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +public interface EchoServiceAsync extends EchoService { + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceImpl.java new file mode 100644 index 00000000..8870bbde --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/EchoServiceImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcClientTest.java new file mode 100644 index 00000000..90240c4b --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcClientTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options; +import io.netty.channel.Channel; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +/** + * Created by wenweihu86 on 2017/4/26. + */ +@SuppressWarnings("unchecked") +public class RpcClientTest { + + public static void main(String[] args) { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(1000); + clientOption.setMaxTotalConnections(1000); + clientOption.setMinIdleConnections(10); +// clientOption.setIoThreadNum(40); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE); + + String serviceUrl = "list://127.0.0.1:8002"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + List interceptors = new ArrayList();; + interceptors.add(new CustomInterceptor()); + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + + // build request + EchoRequest request = new EchoRequest(); + request.setMessage("hellooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"); + + // sync call + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + Channel channel = null; + try { + EchoResponse response = echoService.echo(request); + System.out.printf("sync call service=EchoService.echo success, " + + "request=%s,response=%s\n", + request.getMessage(), response.getMessage()); + } catch (RpcException ex) { + System.out.println("sync call failed, ex=" + ex.getMessage()); + } + rpcClient.stop(); + + // async call + rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + RpcCallback callback = new RpcCallback() { + @Override + public void success(EchoResponse response) { + if (response != null) { + System.out.printf("async call EchoService.echo success, response=%s\n", + response.getMessage()); + } else { + System.out.println("async call failed, service=EchoService.echo"); + } + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call EchoService.echo failed, %s\n", e.getMessage()); + } + }; + EchoServiceAsync asyncEchoService = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + try { + Future future = asyncEchoService.echo(request, callback); + try { + if (future != null) { + future.get(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (RpcException ex) { + System.out.println("rpc send failed, ex=" + ex.getMessage()); + } + rpcClient.stop(); + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcServerTest.java new file mode 100644 index 00000000..e0a1a1a8 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcServerTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.jprotobuf; + +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +public class RpcServerTest { + public static void main(String[] args) { + int port = 8002; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); +// options.setAcceptorThreadNum(8); +// options.setIoThreadNum(32); +// options.setWorkThreadNum(80); + options.setReceiveBufferSize(64 * 1024 * 1024); + options.setSendBufferSize(64 * 1024 * 1024); + RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + // ignore + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcClientTest.java new file mode 100644 index 00000000..0b332185 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcClientTest.java @@ -0,0 +1,42 @@ +package com.baidu.brpc.example.nshead; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.standard.Echo; +import com.baidu.brpc.example.standard.Echo.EchoResponse; +import com.baidu.brpc.example.standard.EchoService; +import com.baidu.brpc.protocol.Options.ProtocolType; + +public class RpcClientTest { + + public static void main(String[] args) { + + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + // clientOption.setProtocolType(ProtocolType.PROTOCOL_NSHEAD_JSON_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(5000); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setEncoding("gbk"); + + // 高端口,在开发机上测试 + String serviceUrl = "list://localhost:8080"; + + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption); + + // sync call + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + + RpcContext.getContext().setLogId(1234); + Echo.EchoRequest request = Echo.EchoRequest.newBuilder().setMessage("hello world").build(); + EchoResponse response = echoService.echo(request); + System.out.println("--------nshead protobuf sync call response-----------------"); + System.out.println(response.getMessage()); + rpcClient.stop(); + + + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcServerTest.java new file mode 100644 index 00000000..135bb445 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcServerTest.java @@ -0,0 +1,33 @@ +package com.baidu.brpc.example.nshead; + +import com.baidu.brpc.example.standard.EchoServiceImpl; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +public class RpcServerTest { + + public static void main(String[] args) { + int port = 8080; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + options.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_PROTOBUF_VALUE); + // options.setProtocolType(Options.ProtocolType.PROTOCOL_NSHEAD_JSON_VALUE); + options.setEncoding("gbk"); + RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + // ignore + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkClientPushTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkClientPushTest.java new file mode 100644 index 00000000..71d81d53 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkClientPushTest.java @@ -0,0 +1,195 @@ +package com.baidu.brpc.example.push; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.example.push.normal.EchoRequest; +import com.baidu.brpc.example.push.normal.EchoResponse; +import com.baidu.brpc.example.push.normal.EchoServiceAsync; +import com.baidu.brpc.example.push.push.UserPushApiImpl; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class BenchmarkClientPushTest { + + public static class SendInfo { + public long successRequestNum = 0; + public long failRequestNum = 0; + public long elapsedNs = 0; + } + + private static volatile boolean stop = false; + + // rpc press: send pressure to RpcServerTest + // push & rpc press: send pressure to BenchmarkServerPushTest + + public static void main(String[] args) { + + if (args.length != 2) { + System.out.println("usage: server_ip:server_port threadNum"); + System.exit(-1); + } + + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(1000); + clientOption.setMaxTotalConnections(1000); +// clientOption.setMaxTotalConnections(10); + clientOption.setMinIdleConnections(100); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE); + clientOption.setClientName("Benchmark"); + + int threadNum = Integer.parseInt(args[1]); + + String serviceUrl = args[0]; +// String serviceUrl = "list://127.0.0.1:8012"; + + List interceptors = new ArrayList(); + interceptors.add(new CustomInterceptor()); + + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption); + EchoServiceAsync echoService = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + rpcClient.registerPushService(new UserPushApiImpl()); + + byte[] messageBytes = null; + try { + InputStream inputStream = Thread.currentThread().getClass() + .getResourceAsStream("/message_1k.txt"); + + int length = inputStream.available(); + messageBytes = new byte[length]; + inputStream.read(messageBytes); + } catch (IOException ex) { + System.exit(1); + } + + SendInfo[] sendInfos = new SendInfo[threadNum]; + Thread[] threads = new Thread[threadNum]; + + for (int i = 0; i < threadNum; i++) { + sendInfos[i] = new SendInfo(); + threads[i] = new Thread(new ThreadTask(messageBytes, sendInfos[i], echoService), "Benchnark-" + i); + threads[i].start(); + } + + long lastSuccessRequestNum = 0; + long lastFailRequestNum = 0; + long lastElapsedNs = 0; + int second = 0; + long skippedQps = 0; + while (!stop) { + long beginTime = System.nanoTime(); + try { + Thread.sleep(1000); + ++second; + + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + + long successNum = 0; + long failNum = 0; + long elapseNs = 0; + long averageElapsedNs = 0; + for (SendInfo sendInfo : sendInfos) { + successNum += sendInfo.successRequestNum; + failNum += sendInfo.failRequestNum; + elapseNs += sendInfo.elapsedNs; + } + if (successNum - lastSuccessRequestNum > 0) { + averageElapsedNs = (elapseNs - lastElapsedNs) / (successNum - lastSuccessRequestNum); + } + long endTime = System.nanoTime(); + + String msg = String.format("success=%s,fail=%s,average=%sns", + (successNum - lastSuccessRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + (failNum - lastFailRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + averageElapsedNs); + + lastSuccessRequestNum = successNum; + lastFailRequestNum = failNum; + lastElapsedNs = elapseNs; + + // 从第10开始计算平均qps + if (second > 30) { + long avgQps = (lastSuccessRequestNum - skippedQps) / (second - 30); + msg = msg + ", avgQps=" + avgQps; + } else { + skippedQps = lastSuccessRequestNum; + } + + log.info(msg); + + } + } + + public static class EchoCallback implements RpcCallback { + private long startTime; + private SendInfo sendInfo; + + public EchoCallback(long startTime, SendInfo sendInfo) { + this.startTime = startTime; + this.sendInfo = sendInfo; + } + + @Override + public void success(EchoResponse response) { + if (response != null) { + sendInfo.successRequestNum++; + long elapseTimeNs = System.nanoTime() - startTime; + sendInfo.elapsedNs += elapseTimeNs; + log.debug("client async call success, elapseTimeNs={}, response={}", + System.nanoTime() - startTime, response.getMessage()); + } else { + sendInfo.failRequestNum++; + log.debug("client async call failed"); + } + } + + @Override + public void fail(Throwable e) { + sendInfo.failRequestNum++; + log.debug("client async call failed, {}", e.getMessage()); + } + } + + public static class ThreadTask implements Runnable { + private byte[] messageBytes; + private SendInfo sendInfo; + private EchoServiceAsync echoService; + + public ThreadTask(byte[] messageBytes, + SendInfo sendInfo, EchoServiceAsync echoService) { + this.messageBytes = messageBytes; + this.sendInfo = sendInfo; + this.echoService = echoService; + } + + public void run() { + // build request + EchoRequest request = new EchoRequest(); + request.setMessage(new String(messageBytes)); + while (!stop) { + try { + echoService.echo(request, new EchoCallback(System.nanoTime(), sendInfo)); + } catch (Exception ex) { + log.info("client send exception:", ex); + sendInfo.failRequestNum++; + } + } + } + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkServerPushTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkServerPushTest.java new file mode 100644 index 00000000..c286db04 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/BenchmarkServerPushTest.java @@ -0,0 +1,178 @@ +package com.baidu.brpc.example.push; + +import com.baidu.brpc.example.push.normal.EchoServiceImpl; +import com.baidu.brpc.example.push.push.PushData; +import com.baidu.brpc.example.push.push.PushResult; +import com.baidu.brpc.example.push.push.ServerSideUserPushApi; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.server.BrpcPushProxy; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.InputStream; + +@Slf4j +public class BenchmarkServerPushTest { + + public static class SendInfo { + public long successRequestNum = 0; + public long failRequestNum = 0; + public long elapsedNs = 0; + } + + private static volatile boolean stop = false; + + // rpc press: send pressure to RpcClientTest + // push & rpc press: send pressure to BenchmarkClientPushTest + + public static void main(String[] args) throws InterruptedException { + + int port = 8012; + + if (args.length != 1) { + System.out.println("usage: threadNum"); + System.exit(-1); + } + + int threadNum = Integer.parseInt(args[0]); + + RpcServerOptions options = new RpcServerOptions(); + options.setReceiveBufferSize(64 * 1024 * 1024); + options.setSendBufferSize(64 * 1024 * 1024); + options.setKeepAliveTime(20); + options.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + + final RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + ServerSideUserPushApi pushApi = BrpcPushProxy.getProxy(rpcServer, ServerSideUserPushApi.class); + rpcServer.start(); + + // wait until the client connected to server + while (!EchoServiceImpl.clientStarted) { + Thread.sleep(1000); + } + + byte[] messageBytes = null; + try { + InputStream inputStream = Thread.currentThread().getClass() + .getResourceAsStream("/message_1k.txt"); + + int length = inputStream.available(); + messageBytes = new byte[length]; + inputStream.read(messageBytes); + } catch (IOException ex) { + System.exit(1); + } + + log.info("message_1k: {}", new String(messageBytes)); + + SendInfo[] sendInfos = new SendInfo[threadNum]; + Thread[] threads = new Thread[threadNum]; + + for (int i = 0; i < threadNum; i++) { + sendInfos[i] = new SendInfo(); + + threads[i] = new Thread(new ServerPushTask(messageBytes, sendInfos[i], pushApi)); + threads[i].start(); + } + + long lastSuccessRequestNum = 0; + long lastFailRequestNum = 0; + long lastElapsedNs = 0; + + int second = 0; + long skippedQps = 0; + + while (!stop) { + + long beginTime = System.nanoTime(); + try { + Thread.sleep(1000); + ++ second; + } catch (Exception e) { + log.error(e.getMessage()); + } + + long successNum = 0; + long failNum = 0; + long elapseNs = 0; + long averageElapsedNs = 0; + + for (SendInfo sendInfo : sendInfos) { + successNum += sendInfo.successRequestNum; + failNum += sendInfo.failRequestNum; + elapseNs += sendInfo.elapsedNs; + } + + if (successNum - lastSuccessRequestNum > 0) { + averageElapsedNs = (elapseNs - lastElapsedNs) / (successNum - lastSuccessRequestNum); + } + long endTime = System.nanoTime(); + + + // 1s : success=request/s; fail=request/s; average= 每个请求的耗时/ns + String msg = String.format("success=%s,fail=%s,average=%sns", + (successNum - lastSuccessRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + (failNum - lastFailRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + averageElapsedNs); + lastSuccessRequestNum = successNum; + lastFailRequestNum = failNum; + lastElapsedNs = elapseNs; + + if ( second > 30 ) { + long avgQps = (lastSuccessRequestNum - skippedQps) / (second - 30); + msg = msg + ",avgQps=" + avgQps; +// log.info("skippedQps:{}, avgQps:{}", skippedQps, avgQps); + } else { + skippedQps = lastSuccessRequestNum; + } + + log.info(msg); + + } + } + + public static class ServerPushTask implements Runnable { + private byte[] messageBytes; + private SendInfo sendInfo; + private ServerSideUserPushApi serverSideUserPushApi; + + public ServerPushTask(byte[] messageBytes, + SendInfo sendInfo, ServerSideUserPushApi serverSideUserPushApi) { + this.messageBytes = messageBytes; + this.sendInfo = sendInfo; + this.serverSideUserPushApi = serverSideUserPushApi; + } + + public void run() { + PushData p = new PushData(); + p.setData(new String(messageBytes)); + + while (!stop) { + try { + long startTime = System.nanoTime(); + PushResult r = serverSideUserPushApi.clientReceive("Benchmark", + "extra", p); + if (r != null && StringUtils.isNotEmpty(r.getResult()) ) { + sendInfo.successRequestNum++; + long elapseTimeNs = System.nanoTime() - startTime; + sendInfo.elapsedNs += elapseTimeNs; + log.debug("sync call success, elapseTimeNs={} ", + System.nanoTime() - startTime); + } else { + sendInfo.failRequestNum++; + log.debug("sync call failed"); + } + } catch (Exception ex) { + log.info("send exception:", ex); + sendInfo.failRequestNum++; + } + } + } + } + + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcClientPushTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcClientPushTest.java new file mode 100644 index 00000000..d0236c4c --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcClientPushTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.push.normal.EchoRequest; +import com.baidu.brpc.example.push.normal.EchoResponse; +import com.baidu.brpc.example.push.normal.EchoService; +import com.baidu.brpc.example.push.normal.EchoService2; +import com.baidu.brpc.example.push.push.UserPushApiImpl; +import com.baidu.brpc.protocol.Options; + +import com.baidu.brpc.utils.GsonUtils; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by wenweihu86 on 2017/4/26. + */ +@SuppressWarnings("unchecked") +@Slf4j +public class RpcClientPushTest { + + public static void main(String[] args) throws InterruptedException { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + clientOption.setWriteTimeoutMillis(20 * 1000); + clientOption.setReadTimeoutMillis(20 * 1000); + clientOption.setMaxTotalConnections(1000); + clientOption.setMinIdleConnections(1); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE); + clientOption.setMaxTotalConnections(1); + + // 指定clientName + clientOption.setClientName("c1"); + + String serviceUrl = "list://127.0.0.1:8002"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + // 创建客户端 c1 + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption); + // 首先建立一个普通rpc client服务, 与后端建立起连接 + final EchoService service1 = BrpcProxy.getProxy(rpcClient, EchoService.class); + // 注册实现push方法 + rpcClient.registerPushService(new UserPushApiImpl()); + + final EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + + Thread thread1 = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + EchoResponse response = service1.echo(request); + System.out.println("res1=" + GsonUtils.toJson(response)); + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + }); + thread1.start(); + + // 创建客户端c2 + clientOption.setClientName("c2"); + RpcClient rpcClient2 = new RpcClient(serviceUrl, clientOption); + final EchoService2 service2 = BrpcProxy.getProxy(rpcClient2, EchoService2.class); + rpcClient2.registerPushService(new UserPushApiImpl()); + + Thread thread2 = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + EchoResponse response = service2.echo(request); + System.out.println("res=2" + GsonUtils.toJson(response)); + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + }); + thread2.start(); + + synchronized(RpcClientPushTest.class) { + try { + RpcClientPushTest.class.wait(); + } catch (Throwable e) { + } + } + + thread1.join(); + thread2.join(); + rpcClient.stop(); + rpcClient2.stop(); + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcServerPushTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcServerPushTest.java new file mode 100644 index 00000000..87a49a83 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcServerPushTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push; + +import com.baidu.brpc.example.push.normal.EchoService2Impl; +import com.baidu.brpc.example.push.normal.EchoServiceImpl; +import com.baidu.brpc.example.push.push.PushData; +import com.baidu.brpc.example.push.push.PushResult; +import com.baidu.brpc.example.push.push.ServerSideUserPushApi; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.server.BrpcPushProxy; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.utils.GsonUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +@Slf4j +public class RpcServerPushTest { + + public static void main(String[] args) throws InterruptedException { + int port = 8002; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + options.setReceiveBufferSize(64 * 1024 * 1024); + options.setSendBufferSize(64 * 1024 * 1024); + options.setKeepAliveTime(20); + options.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); +// options.setNamingServiceUrl("zookeeper://127.0.0.1:2181"); + + final RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.registerService(new EchoService2Impl()); + + // get push api + ServerSideUserPushApi proxyPushApi = BrpcPushProxy.getProxy(rpcServer, ServerSideUserPushApi.class); + rpcServer.start(); + + // wait until the client connected to server + while (!EchoServiceImpl.clientStarted || !EchoService2Impl.client2Started) { + Thread.sleep(1000); + } + + // test clientname exist or not + try { + PushData p1 = new PushData(); + p1.setData("hellooooo"); + PushResult pushResultI = proxyPushApi.clientReceive("c3","c3", p1); + log.info("push result: {}" , GsonUtils.toJson(pushResultI) ); + } catch (Exception e) { + log.error("case one--clientname not exist, exception: {}", e.getMessage()); + } + + // push data to 2 clients : "c1" and "c2" + int i = 0; + while (true) { + i++; + PushData p = new PushData(); + p.setData("pushData" + i); + int index = i % 2 + 1; + String clientName = "c" + index; + String extra = "c" + (index + 100); + log.info("pushing data to client:" + clientName); + try { + // last param of api is clientName + PushResult pushResult = proxyPushApi.clientReceive(clientName, extra, p); + log.info("received push result:" + GsonUtils.toJson(pushResult)); + } catch (Exception e) { + log.error("push exception , please start up client c1 and c2", e); + } + + Thread.sleep(1000); + } + + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoRequest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoRequest.java new file mode 100644 index 00000000..d1b1f481 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoRequest.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoResponse.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoResponse.java new file mode 100644 index 00000000..6d27d053 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoResponse.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService.java new file mode 100644 index 00000000..29148076 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +public interface EchoService { + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2.java new file mode 100644 index 00000000..ddaf3e73 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +public interface EchoService2 { + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Async.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Async.java new file mode 100644 index 00000000..b278d4fb --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Async.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +public interface EchoService2Async extends EchoService2 { + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Impl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Impl.java new file mode 100644 index 00000000..73b9dc73 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoService2Impl.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EchoService2Impl implements EchoService2 { + private static final Logger LOG = LoggerFactory.getLogger(EchoService2Impl.class); + public static volatile boolean client2Started = false; + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + client2Started = true; + return response; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceAsync.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceAsync.java new file mode 100644 index 00000000..5fdac191 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceAsync.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +public interface EchoServiceAsync extends EchoService { + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceImpl.java new file mode 100644 index 00000000..19e325c1 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/normal/EchoServiceImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.push.normal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + public static volatile boolean clientStarted = false; + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + clientStarted = true; + return response; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushData.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushData.java new file mode 100644 index 00000000..08859c65 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushData.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.example.push.push; + +public class PushData { + + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushResult.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushResult.java new file mode 100644 index 00000000..dce9e84d --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/PushResult.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.example.push.push; + +public class PushResult { + + public String result; + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/ServerSideUserPushApi.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/ServerSideUserPushApi.java new file mode 100644 index 00000000..44922f5f --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/ServerSideUserPushApi.java @@ -0,0 +1,15 @@ +package com.baidu.brpc.example.push.push; + +public interface ServerSideUserPushApi extends UserPushApi { + + /** + * server端接口, 多一个clientName参数 + * + * @param clientName + * @param data + * + * @return + */ + PushResult clientReceive(String clientName, String extra, PushData data); + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApi.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApi.java new file mode 100644 index 00000000..53b113d6 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApi.java @@ -0,0 +1,7 @@ +package com.baidu.brpc.example.push.push; + +public interface UserPushApi { + + PushResult clientReceive(String extra, PushData data); + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApiImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApiImpl.java new file mode 100644 index 00000000..a3db2119 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/push/UserPushApiImpl.java @@ -0,0 +1,14 @@ +package com.baidu.brpc.example.push.push; + + +public class UserPushApiImpl implements UserPushApi { + + @Override + public PushResult clientReceive(String extra, PushData data) { + // System.out.println("++invoke clientReceive :" + data.getData()); + PushResult pushResult = new PushResult(); + pushResult.setResult(extra + " receive push data:" + data.getData()); + return pushResult; + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/AsyncEchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/AsyncEchoService.java new file mode 100644 index 00000000..b26bc700 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/AsyncEchoService.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.api; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.protocol.BrpcMeta; + +import java.util.concurrent.Future; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface AsyncEchoService extends EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoRequest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoRequest.java new file mode 100644 index 00000000..896c6a5c --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoResponse.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoResponse.java new file mode 100644 index 00000000..f512fef6 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoService.java new file mode 100644 index 00000000..b9d35fee --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/api/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.api; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacade.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacade.java new file mode 100644 index 00000000..a9de5f5b --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacade.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.client; + +import com.baidu.brpc.example.spring.api.EchoRequest; +import com.baidu.brpc.example.spring.api.EchoResponse; + +import java.util.concurrent.Future; + +public interface EchoFacade { + EchoResponse echo(EchoRequest request); + EchoResponse echo2(EchoRequest request); + Future echo3(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacadeImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacadeImpl.java new file mode 100644 index 00000000..597fea58 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/EchoFacadeImpl.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.client; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.example.spring.api.AsyncEchoService; +import com.baidu.brpc.example.spring.api.EchoRequest; +import com.baidu.brpc.example.spring.api.EchoResponse; +import com.baidu.brpc.example.spring.api.EchoService; +import com.baidu.brpc.spring.annotation.RpcProxy; +import lombok.Getter; +import lombok.Setter; +import org.springframework.stereotype.Service; + +import java.util.concurrent.Future; + +@Service +@Setter +@Getter +public class EchoFacadeImpl implements EchoFacade { + @RpcProxy(rpcClientOptionsBeanName = "rpcClientOptions", + interceptorBeanNames = "customInterceptor") + private EchoService echoService; + + @RpcProxy(rpcClientOptionsBeanName = "rpcClientOptions", + interceptorBeanNames = "customInterceptor") + private EchoService echoService2; + + /** + * async service interface proxy will create new RpcClient, + * not used RpcClient of sync interface proxy. + */ + @RpcProxy(rpcClientOptionsBeanName = "rpcClientOptions", + interceptorBeanNames = "customInterceptor") + private AsyncEchoService echoService3; + + public EchoResponse echo(EchoRequest request) { + System.out.println(echoService.hashCode()); + return echoService.echo(request); + } + + public EchoResponse echo2(EchoRequest request) { + System.out.println(echoService2.hashCode()); + return echoService2.echo(request); + } + + public Future echo3(EchoRequest request) { + System.out.println(echoService3.hashCode()); + Future future = echoService3.echo(request, new RpcCallback() { + @Override + public void success(EchoResponse response) { + System.out.println(response.getMessage()); + } + + @Override + public void fail(Throwable e) { + e.printStackTrace(); + } + }); + return future; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/RpcClientTest.java new file mode 100644 index 00000000..f859daf7 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/client/RpcClientTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.client; + +import com.baidu.brpc.example.spring.api.EchoRequest; +import com.baidu.brpc.example.spring.api.EchoResponse; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.concurrent.Future; + +public class RpcClientTest { + public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "classpath:applicationContext.client.xml"); + context.start(); + + EchoFacade facade = context.getBean("echoFacadeImpl", EchoFacade.class); + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + EchoResponse response = facade.echo(request); + System.out.println(response.getMessage()); + + EchoResponse response2 = facade.echo2(request); + System.out.println(response2.getMessage()); + + Future future = facade.echo3(request); + try { + future.get(); + } catch (Exception ex) { + // ignore + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/EchoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/EchoServiceImpl.java new file mode 100644 index 00000000..aa804484 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/EchoServiceImpl.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.server; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.baidu.brpc.example.spring.api.EchoRequest; +import com.baidu.brpc.example.spring.api.EchoResponse; +import com.baidu.brpc.example.spring.api.EchoService; +import com.baidu.brpc.spring.annotation.NamingOption; +import com.baidu.brpc.spring.annotation.RpcExporter; + +@Service("echoServiceImpl") +@RpcExporter(port = "8012", + useServiceSharedThreadPool = false, + rpcServerOptionsBeanName = "rpcServerOptions", + interceptorBeanNames = "customInterceptor", + extraOptions = { + // We can pass extra options to the NamingService + // `weight` is just an example here, currently we don't have any NamingService supports weight yet + @NamingOption(key = "weight", value = "10") + } +) +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public EchoResponse echo(EchoRequest request) { + // 读取request attachment +// RpcContext rpcContext = RpcContext.getContext(); +// ByteBuf attachment = rpcContext.getRequestBinaryAttachment(); +// if (attachment != null) { +// if (LOG.isDebugEnabled()) { +// String attachmentString = new String(attachment.array()); +// LOG.debug("request attachment={}", attachmentString); +// } +// // 设置response attachment +// rpcContext.setResponseBinaryAttachment(Unpooled.copiedBuffer(attachment)); +// } + + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/RpcServerTest.java new file mode 100644 index 00000000..bc936d0e --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/spring/server/RpcServerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.spring.server; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class RpcServerTest { + public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "classpath:applicationContext.server.xml"); + context.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/BenchmarkTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/BenchmarkTest.java new file mode 100644 index 00000000..49c1b03d --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/BenchmarkTest.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import java.io.IOException; +import java.io.InputStream; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.protocol.Options; + +import io.netty.util.ReferenceCountUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by wenweihu86 on 2017/5/1. + */ +@Slf4j +public class BenchmarkTest { + public static class SendInfo { + public long successRequestNum = 0; + public long failRequestNum = 0; + public long elapsedNs = 0; + } + + private static volatile boolean stop = false; + + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("usage: BenchmarkTest 127.0.0.1:8002 threadNum"); + System.exit(-1); + } + RpcClientOptions options = new RpcClientOptions(); + options.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + options.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + options.setMaxTotalConnections(1000000); + options.setMinIdleConnections(10); + options.setConnectTimeoutMillis(1000); + options.setWriteTimeoutMillis(1000); + options.setReadTimeoutMillis(1000); + options.setTcpNoDelay(false); + options.setChannelType(ChannelType.SINGLE_CONNECTION); +// options.setWorkThreadNum(2); + // options.setFutureBufferSize(10000); + RpcClient rpcClient = new RpcClient(args[0], options); + int threadNum = Integer.parseInt(args[1]); + + byte[] messageBytes = null; + try { + InputStream inputStream = Thread.currentThread().getClass() + .getResourceAsStream("/message_1k.txt"); + int length = inputStream.available(); + messageBytes = new byte[length]; + inputStream.read(messageBytes); + log.info("message size=" + messageBytes.length); + } catch (IOException ex) { + System.exit(1); + } + + EchoServiceAsync echoService = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + + SendInfo[] sendInfos = new SendInfo[threadNum]; + Thread[] threads = new Thread[threadNum]; + for (int i = 0; i < threadNum; i++) { + sendInfos[i] = new SendInfo(); + threads[i] = new Thread(new ThreadTask(rpcClient, messageBytes, sendInfos[i], echoService), + "work-thread-" + i); + threads[i].start(); + } + + long lastSuccessRequestNum = 0; + long lastFailRequestNum = 0; + long lastElapsedNs = 0; + int second = 0; + long skippedQps = 0; + while (!stop) { + long beginTime = System.nanoTime(); + try { + Thread.sleep(1000); + ++second; + + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + + long successNum = 0; + long failNum = 0; + long elapseNs = 0; + long averageElapsedNs = 0; + for (SendInfo sendInfo : sendInfos) { + successNum += sendInfo.successRequestNum; + failNum += sendInfo.failRequestNum; + elapseNs += sendInfo.elapsedNs; + } + if (successNum - lastSuccessRequestNum > 0) { + averageElapsedNs = (elapseNs - lastElapsedNs) / (successNum - lastSuccessRequestNum); + } + long endTime = System.nanoTime(); + + String msg = String.format("success=%s,fail=%s,average=%sns", + (successNum - lastSuccessRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + (failNum - lastFailRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + averageElapsedNs); + + lastSuccessRequestNum = successNum; + lastFailRequestNum = failNum; + lastElapsedNs = elapseNs; + + // 从第10开始计算平均qps + if (second > 30) { + long avgQps = (lastSuccessRequestNum - skippedQps) / (second - 30); + msg = msg + ", avgQps=" + avgQps; + } else { + skippedQps = lastSuccessRequestNum; + } + + log.info(msg); + + } + } + + public static class EchoCallback implements RpcCallback { + private long startTime; + private SendInfo sendInfo; + + public EchoCallback(long startTime, SendInfo sendInfo) { + this.startTime = startTime; + this.sendInfo = sendInfo; + } + + @Override + public void success(Echo.EchoResponse response) { + if (response != null) { + sendInfo.successRequestNum++; + long elapseTimeNs = System.nanoTime() - startTime; + sendInfo.elapsedNs += elapseTimeNs; + if (RpcContext.isSet()) { + RpcContext rpcContext = RpcContext.getContext(); + if (rpcContext.getResponseBinaryAttachment() != null) { + ReferenceCountUtil.release(rpcContext.getResponseBinaryAttachment()); + } + } + log.debug("async call success, elapseTimeNs={}, response={}", + System.nanoTime() - startTime, response.getMessage()); + } else { + sendInfo.failRequestNum++; + log.debug("async call failed"); + } + } + + @Override + public void fail(Throwable e) { + sendInfo.failRequestNum++; + log.debug("async call failed, {}", e.getMessage()); + } + } + + public static class ThreadTask implements Runnable { + + private RpcClient rpcClient; + private byte[] messageBytes; + private SendInfo sendInfo; + private EchoServiceAsync echoService; + + public ThreadTask(RpcClient rpcClient, byte[] messageBytes, + SendInfo sendInfo, EchoServiceAsync echoService) { + this.rpcClient = rpcClient; + this.messageBytes = messageBytes; + this.sendInfo = sendInfo; + this.echoService = echoService; + } + + public void run() { + // build request + Echo.EchoRequest request = Echo.EchoRequest.newBuilder() + .setMessage(new String(messageBytes)) + .build(); + byte[] attachment = "hello".getBytes(); + + while (!stop) { + try { + RpcContext rpcContext = RpcContext.getContext(); + rpcContext.setRequestBinaryAttachment(attachment); + echoService.echo(request, new EchoCallback(System.nanoTime(), sendInfo)); + } catch (Exception ex) { + log.info("send exception:", ex); + sendInfo.failRequestNum++; + } + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoService.java new file mode 100644 index 00000000..267b7485 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu/public_pbrpc: + * serviceName默认是类名,不需要加包名,methodName是proto文件Service内对应方法index,默认从0开始。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + Echo.EchoResponse echo(Echo.EchoRequest request); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceAsync.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceAsync.java new file mode 100644 index 00000000..c8208710 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceAsync.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import com.baidu.brpc.client.RpcCallback; + +import java.util.concurrent.Future; + +/** + * Created by baidu on 2017/9/23. + */ +public interface EchoServiceAsync extends EchoService { + Future echo(Echo.EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceImpl.java new file mode 100644 index 00000000..df63eb79 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/EchoServiceImpl.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.RpcContext; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public Echo.EchoResponse echo(Echo.EchoRequest request) { + // 读取request attachment + if (RpcContext.isSet()) { + RpcContext rpcContext = RpcContext.getContext(); + String remoteHost = rpcContext.getRemoteHost(); + LOG.debug("remote host:{}", remoteHost); + ByteBuf attachment = rpcContext.getRequestBinaryAttachment(); + if (attachment != null) { + if (LOG.isDebugEnabled()) { + String attachmentString = new String(attachment.array()); + LOG.debug("request attachment={}", attachmentString); + } + // 设置response attachment + rpcContext.setResponseBinaryAttachment(Unpooled.copiedBuffer(attachment)); + } + } + + String message = request.getMessage(); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage(message).build(); +// LOG.debug("EchoService.echo, request={}, response={}", +// request.getMessage(), response.getMessage()); + + return response; + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcClientTest.java new file mode 100644 index 00000000..41590a11 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcClientTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.example.interceptor.CustomInterceptor; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +/** + * Created by wenweihu86 on 2017/4/26. + */ +@SuppressWarnings("unchecked") +@Slf4j +public class RpcClientTest { + + public static void main(String[] args) { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(5000); + clientOption.setMaxTotalConnections(1000); + clientOption.setMinIdleConnections(10); + clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE); + + String serviceUrl = "list://127.0.0.1:8002"; +// String serviceUrl = "zookeeper://127.0.0.1:2181"; + if (args.length == 1) { + serviceUrl = args[0]; + } + + // build request + Echo.EchoRequest request = Echo.EchoRequest.newBuilder() + .setMessage("helloooooooooooo") + .build(); + + List interceptors = new ArrayList(); + interceptors.add(new CustomInterceptor()); + + // sync call + RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); +// RpcClient rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + RpcContext.getContext().setLogId(1234); + try { + Echo.EchoResponse response = echoService.echo(request); + System.out.printf("sync call service=EchoService.echo success, " + + "request=%s,response=%s\n", + request.getMessage(), response.getMessage()); + } catch (RpcException ex) { + log.warn("sync call failed, ex=", ex); + } + rpcClient.stop(); + + // async call + rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); +// rpcClient = new RpcClient(serviceUrl, clientOption, interceptors); + RpcCallback callback = new RpcCallback() { + @Override + public void success(Echo.EchoResponse response) { + System.out.printf("async call EchoService.echo success, response=%s\n", + response.getMessage()); + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call EchoService.echo failed, %s\n", e.getMessage()); + } + }; + EchoServiceAsync asyncEchoService = BrpcProxy.getProxy(rpcClient, EchoServiceAsync.class); + try { + Future future = asyncEchoService.echo(request, callback); + try { + Echo.EchoResponse response = future.get(1000, TimeUnit.MILLISECONDS); + System.out.println("response from future:" + response.getMessage()); + } catch (Exception ex1) { + ex1.printStackTrace(); + } + } catch (RpcException ex) { + System.out.println("rpc send failed, ex=" + ex.getMessage()); + } + rpcClient.stop(); + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcServerTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcServerTest.java new file mode 100644 index 00000000..e27899ca --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcServerTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by wenweihu86 on 2017/4/25. + */ +@Slf4j +public class RpcServerTest { + public static void main(String[] args) { + int port = 8002; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + options.setReceiveBufferSize(64 * 1024 * 1024); + options.setSendBufferSize(64 * 1024 * 1024); + options.setKeepAliveTime(20); +// options.setNamingServiceUrl("zookeeper://127.0.0.1:2181"); +// final RpcServer rpcServer = new RpcServer(port, options); + final RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SingleConnectionClientTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SingleConnectionClientTest.java new file mode 100644 index 00000000..30350e4b --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SingleConnectionClientTest.java @@ -0,0 +1,109 @@ +package com.baidu.brpc.example.standard; + +import java.util.List; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceType; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Options; +import com.google.common.collect.Lists; + +import io.netty.util.ReferenceCountUtil; + +@SuppressWarnings("unchecked") +public class SingleConnectionClientTest { + + private static final Logger LOG = LoggerFactory.getLogger(SingleConnectionClientTest.class); + + public static final int PERIOD = 1000; + + public static void main(String[] args) { + + String serviceUrl = "list://127.0.0.1:8002"; + + List interceptors = Lists.newArrayList(); + RpcClient rpcClient = new RpcClient(serviceUrl, getRpcClientOptions(), interceptors); + + // build request + final Echo.EchoRequest request = Echo.EchoRequest.newBuilder() + .setMessage("test single connection").build(); + + // sync call + final EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + ScheduledExecutorService schedule = Executors.newScheduledThreadPool(10); + final AtomicInteger counter = new AtomicInteger(0); + final Random random = new Random(System.currentTimeMillis()); + + schedule.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + int index = counter.getAndIncrement(); + int countInHalfMinute = 30 * 1000000 / PERIOD; + if (((index / countInHalfMinute) & 1) == 1) { + return; + } + RpcContext rpcContext = RpcContext.getContext(); + rpcContext.setRequestBinaryAttachment("example attachment".getBytes()); + Echo.EchoResponse response = echoService.echo(request); + // sample log + if (random.nextInt(10000) < 30) { + LOG.info("sync call service=EchoService.echo success, " + + "request={},response={}", + request.getMessage(), response.getMessage()); + } + rpcContext = RpcContext.getContext(); + if (rpcContext.getResponseBinaryAttachment() != null) { + LOG.info("attachment=" + + new String(rpcContext.getResponseBinaryAttachment().array())); + ReferenceCountUtil.release(rpcContext.getResponseBinaryAttachment()); + } + } catch (RpcException ex) { + if (random.nextInt(10000) < 30) { + LOG.error("sync call failed, ex=" + ex.getMessage()); + } + } catch (Exception e) { + LOG.info("other exception, {}", e); + } + } + }, 100000, PERIOD, TimeUnit.MICROSECONDS); + + while (counter.get() < 1000000) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + LOG.info("count:{}", counter.get()); + } + schedule.shutdown(); + rpcClient.stop(); + } + + private static RpcClientOptions getRpcClientOptions() { + RpcClientOptions clientOption = new RpcClientOptions(); + clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + clientOption.setWriteTimeoutMillis(1000); + clientOption.setReadTimeoutMillis(1000); + clientOption.setMaxTotalConnections(1000); + clientOption.setMinIdleConnections(10); + clientOption.setLoadBalanceType(LoadBalanceType.ROUND_ROBIN.getId()); + clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE); + clientOption.setChannelType(ChannelType.SINGLE_CONNECTION); + clientOption.setKeepAliveTime(25); + return clientOption; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SyncBenchmarkTest.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SyncBenchmarkTest.java new file mode 100644 index 00000000..965fd108 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/SyncBenchmarkTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.standard; + +import java.io.IOException; +import java.io.InputStream; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.client.channel.ChannelType; +import com.baidu.brpc.client.loadbalance.LoadBalanceStrategy; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.protocol.Options; + +import io.netty.util.ReferenceCountUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by huwenwei on 2017/5/1. + */ +@Slf4j +public class SyncBenchmarkTest { + + private static volatile boolean stop = false; + + public static class SendInfo { + public long successRequestNum = 0; + public long failRequestNum = 0; + public long elapsedNs = 0; + } + + public static void main(String[] args) throws InterruptedException, IOException { + if (args.length != 2) { + System.out.println("usage: BenchmarkTest list://127.0.0.1:8002 threadNum"); + System.exit(-1); + } + RpcClientOptions options = new RpcClientOptions(); + options.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE); + options.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR); + options.setMaxTotalConnections(1000000); + options.setMinIdleConnections(10); + options.setConnectTimeoutMillis(100); + options.setWriteTimeoutMillis(100); + options.setReadTimeoutMillis(100); + options.setTcpNoDelay(false); + options.setMaxTryTimes(1); + options.setChannelType(ChannelType.SINGLE_CONNECTION); + RpcClient rpcClient = new RpcClient(args[0], options, null); + int threadNum = Integer.parseInt(args[1]); + + InputStream inputStream = Thread.currentThread().getClass() + .getResourceAsStream("/message.txt"); + int length = inputStream.available(); + byte[] messageBytes = new byte[length]; + inputStream.read(messageBytes); + log.info("message size=" + messageBytes.length); + + EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class); + + SendInfo[] sendInfos = new SendInfo[threadNum]; + Thread[] threads = new Thread[threadNum]; + + for (int i = 0; i < threadNum; i++) { + sendInfos[i] = new SendInfo(); + threads[i] = new Thread(new ThreadTask(i, rpcClient, messageBytes, sendInfos[i], echoService), + "work-thread-" + i); + threads[i].start(); + } + long lastSuccessRequestNum = 0; + long lastFailRequestNum = 0; + long lastElapsedNs = 0; + while (!stop) { + long beginTime = System.nanoTime(); + try { + Thread.sleep(1000); + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + long successNum = 0; + long failNum = 0; + long elapseNs = 0; + long averageElapsedNs = 0; + for (SendInfo sendInfo : sendInfos) { + successNum += sendInfo.successRequestNum; + failNum += sendInfo.failRequestNum; + elapseNs += sendInfo.elapsedNs; + } + if (successNum - lastSuccessRequestNum > 0) { + averageElapsedNs = (elapseNs - lastElapsedNs) / (successNum - lastSuccessRequestNum); + } + long endTime = System.nanoTime(); + log.info("success={},fail={},average={}ns", + (successNum - lastSuccessRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + (failNum - lastFailRequestNum) * 1000 * 1000 * 1000 / (endTime - beginTime), + averageElapsedNs); + lastSuccessRequestNum = successNum; + lastFailRequestNum = failNum; + lastElapsedNs = elapseNs; + } + } + + public static class ThreadTask implements Runnable { + private int id; + private RpcClient rpcClient; + private byte[] messageBytes; + private SendInfo sendInfo; + private EchoService echoService; + + public ThreadTask(int id, RpcClient rpcClient, byte[] messageBytes, + SendInfo sendInfo, EchoService echoService) { + this.id = id; + this.rpcClient = rpcClient; + this.messageBytes = messageBytes; + this.sendInfo = sendInfo; + this.echoService = echoService; + } + + public void run() { + // build request + Echo.EchoRequest request = Echo.EchoRequest.newBuilder() + .setMessage("hello" + id) + .build(); + + while (!stop) { + try { + RpcContext rpcContext = RpcContext.getContext(); + rpcContext.setRequestBinaryAttachment(messageBytes); + long beginTime = System.nanoTime(); + Echo.EchoResponse response = echoService.echo(request); + if (!response.getMessage().equals(request.getMessage())) { + log.warn("id:{} request:{}, response:{}", id, request.getMessage(), response.getMessage()); + } + sendInfo.elapsedNs += (System.nanoTime() - beginTime); + sendInfo.successRequestNum++; + rpcContext = RpcContext.getContext(); + if (rpcContext.getResponseBinaryAttachment() != null) { + ReferenceCountUtil.release(rpcContext.getResponseBinaryAttachment()); + } + } catch (RpcException ex) { + log.info("send exception:" + ex.getMessage()); + sendInfo.failRequestNum++; + } + } + } + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoClient.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoClient.java new file mode 100644 index 00000000..a39eb18f --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoClient.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.zookeeper.StargateNamingFactory; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.utils.GsonUtils; + +public class StargateDemoClient { + + public static void main(String[] args) { + RpcClientOptions options = new RpcClientOptions(); + // Stargate 协议需要强指定协议类型,不可使用BRPC协议解析器 + options.setProtocolType(Options.ProtocolType.PROTOCOL_STARGATE_VALUE); + options.setReadTimeoutMillis(1000); + options.setWriteTimeoutMillis(1000); + RpcClient rpcClient = new RpcClient(StargateDemoConstant.namingUrl, options); + + NamingOptions namingOptions = new NamingOptions(); + namingOptions.setGroup(StargateDemoConstant.group); + namingOptions.setVersion(StargateDemoConstant.version); + + StargateDemoService proxy = BrpcProxy.getProxy(rpcClient, StargateDemoService.class, namingOptions); + + for (int i = 0, times = 10; i < times; i++) { + RpcContext rpcContext = RpcContext.getContext(); + rpcContext.reset(); + rpcContext.setRequestKvAttachment("key", "value"); + StargateDemoReqDto reqDto = new StargateDemoReqDto(); + reqDto.setId(1000L); + reqDto.setName("test"); + StargateDemoResDto call = proxy.call(reqDto); + System.out.println(GsonUtils.toJson(call)); + if (rpcContext.getResponseKvAttachment() != null) { + System.out.println(rpcContext.getResponseKvAttachment().get("resKey")); + } + System.out.println(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + rpcClient.stop(); + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoConstant.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoConstant.java new file mode 100644 index 00000000..c1f30d62 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoConstant.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +public interface StargateDemoConstant { + + String version = "1.0.0"; + + String group = "normal"; + + /** + * star 并无特殊含义,单纯只是长得像 + */ + String namingUrl = "star://127.0.0.1:2181/stargate"; + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoReqDto.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoReqDto.java new file mode 100644 index 00000000..3a97eb35 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoReqDto.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class StargateDemoReqDto { + + private Long id; + + private String name; + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoResDto.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoResDto.java new file mode 100644 index 00000000..2ecb03b3 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoResDto.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@Builder +public class StargateDemoResDto { + + private Long id; + + private String name; + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServer.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServer.java new file mode 100644 index 00000000..02f0aae7 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServer.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.protocol.Options; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +public class StargateDemoServer { + + public static void main(String[] args) { + RpcServerOptions serverOptions = new RpcServerOptions(); + serverOptions.setProtocolType(Options.ProtocolType.PROTOCOL_STARGATE_VALUE); + serverOptions.setNamingServiceUrl(StargateDemoConstant.namingUrl); + + RpcServer rpcServer = new RpcServer(8898, serverOptions); + StargateDemoService demoService = new StargateDemoServiceImpl(); + + NamingOptions namingOptions = new NamingOptions(); + namingOptions.setGroup(StargateDemoConstant.group); + namingOptions.setVersion(StargateDemoConstant.version); + + rpcServer.registerService(demoService, namingOptions); + rpcServer.start(); + + // make server keep running + synchronized (StargateDemoServer.class) { + try { + StargateDemoServer.class.wait(); + } catch (Throwable e) { + } + } + } + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoService.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoService.java new file mode 100644 index 00000000..974628b5 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoService.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import java.util.List; +import java.util.Map; + +public interface StargateDemoService { + + StargateDemoResDto call(StargateDemoReqDto reqDto); + + List list(StargateDemoReqDto reqDto); + + Map map(StargateDemoReqDto reqDto); + +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServiceImpl.java b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServiceImpl.java new file mode 100644 index 00000000..1dc26c22 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/stargate/StargateDemoServiceImpl.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.example.stargate; + +import com.baidu.brpc.RpcContext; +import com.baidu.brpc.utils.GsonUtils; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class StargateDemoServiceImpl implements StargateDemoService { + + @Override + public StargateDemoResDto call(StargateDemoReqDto reqDto) { + if (log.isDebugEnabled()) { + log.debug("rev from server {}", GsonUtils.toJson(reqDto)); + RpcContext rpcContext = RpcContext.getContext(); + Map attachment = rpcContext.getRequestKvAttachment(); + if (attachment != null) { + log.info("request attachment:{}", attachment.get("key")); + rpcContext.setResponseKvAttachment("resKey", attachment.get("key")); + } + } + return StargateDemoResDto.builder().id(reqDto.getId()).name(reqDto.getName()).build(); + } + + @Override + public List list(StargateDemoReqDto reqDto) { + if (log.isDebugEnabled()) { + log.info("rev from server {}", GsonUtils.toJson(reqDto)); + } + List list = new ArrayList(); + for (int i = 0; i < reqDto.getId(); i++) { + list.add(StargateDemoResDto.builder().id(reqDto.getId()).name(reqDto.getName()).build()); + } + return list; + } + + @Override + public Map map(StargateDemoReqDto reqDto) { + if (log.isDebugEnabled()) { + log.info("rev from server {}", GsonUtils.toJson(reqDto)); + } + Map map = new HashMap(); + StargateDemoResDto build = StargateDemoResDto.builder().id(reqDto.getId()).name(reqDto.getName()).build(); + map.put(reqDto.getId(), build); + return map; + } +} diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/proto/echo.proto b/brpc-java-examples/brpc-java-core-examples/src/main/proto/echo.proto new file mode 100644 index 00000000..7a3b6d75 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/proto/echo.proto @@ -0,0 +1,18 @@ +syntax="proto2"; + +package example_for_cpp; +option java_package="com.baidu.brpc.example.standard"; +option java_outer_classname="Echo"; +option cc_generic_services = true; + +message EchoRequest { + required string message = 1; +}; + +message EchoResponse { + required string message = 1; +}; + +service EchoService { + rpc Echo(EchoRequest) returns (EchoResponse); +}; diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.client.xml b/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.client.xml new file mode 100644 index 00000000..0de24611 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.client.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.server.xml b/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.server.xml new file mode 100644 index 00000000..f76168ab --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/applicationContext.server.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/logback.xml b/brpc-java-examples/brpc-java-core-examples/src/main/resources/logback.xml new file mode 100644 index 00000000..9d77be39 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/logback.xml @@ -0,0 +1,54 @@ + + + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + logs/echo-all.%d{yyyy-MM-dd}.log + + 60 + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + logs/echo-warn.%d{yyyy-MM-dd}.log + + 120 + + + WARN + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + + + + + + + + + + + diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/message.txt b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message.txt new file mode 100644 index 00000000..b6fc4c62 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message.txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_1k.txt b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_1k.txt new file mode 100644 index 00000000..8bfcfc8a --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_1k.txt @@ -0,0 +1,20 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_2k.txt b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_2k.txt new file mode 100644 index 00000000..373c659d --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_2k.txt @@ -0,0 +1,40 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_4k.txt b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_4k.txt new file mode 100644 index 00000000..eb9e1ba0 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/message_4k.txt @@ -0,0 +1,80 @@ +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello +hellohellohellohellohellohellohellohellohellohello \ No newline at end of file diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/server_list.conf b/brpc-java-examples/brpc-java-core-examples/src/main/resources/server_list.conf new file mode 100644 index 00000000..fa7b63f5 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/server_list.conf @@ -0,0 +1 @@ +127.0.0.1:8002 diff --git a/brpc-java-examples/brpc-java-core-examples/src/main/resources/test_server_list.txt b/brpc-java-examples/brpc-java-core-examples/src/main/resources/test_server_list.txt new file mode 100644 index 00000000..4fc894a2 --- /dev/null +++ b/brpc-java-examples/brpc-java-core-examples/src/main/resources/test_server_list.txt @@ -0,0 +1,2 @@ +127.0.0.1:8002 +invalid will skip diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/pom.xml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/pom.xml new file mode 100644 index 00000000..0f914648 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/pom.xml @@ -0,0 +1,89 @@ + + + + 4.0.0 + + + com.baidu + brpc-spring-boot-examples + 2.5.9 + + + brpc-spring-boot-examples-api + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + release + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/AsyncEchoService.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/AsyncEchoService.java new file mode 100644 index 00000000..60b2d697 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/AsyncEchoService.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.api; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.protocol.BrpcMeta; + +import java.util.concurrent.Future; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface AsyncEchoService extends EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoRequest.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoRequest.java new file mode 100644 index 00000000..e3eadc76 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoResponse.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoResponse.java new file mode 100644 index 00000000..d689c9fe --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoService.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoService.java new file mode 100644 index 00000000..daaf5cbf --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-api/src/main/java/com/baidu/brpc/example/springboot/api/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.api; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/pom.xml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/pom.xml new file mode 100644 index 00000000..eaf435d7 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/pom.xml @@ -0,0 +1,135 @@ + + + + 4.0.0 + + + com.baidu + brpc-spring-boot-examples + 2.5.9 + + + brpc-spring-boot-examples-client + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + release + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + + + + com.baidu + brpc-spring-boot-examples-api + ${project.version} + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + com.baidu + brpc-java-naming-zookeeper + + + org.springframework.boot + spring-boot-starter-web + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + ${project.name} + + + org.springframework.boot + spring-boot-maven-plugin + + com.baidu.brpc.example.springboot.client.RpcClientTest + + + + + repackage + + + + + + + + diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/BrpcConfigs.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/BrpcConfigs.java new file mode 100644 index 00000000..5ba87bf6 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/BrpcConfigs.java @@ -0,0 +1,13 @@ +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.interceptor.Interceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BrpcConfigs { + @Bean + public Interceptor customInterceptor() { + return new CustomInterceptor(); + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/CustomInterceptor.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/CustomInterceptor.java new file mode 100644 index 00000000..2ccbaa96 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/CustomInterceptor.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.interceptor.AbstractInterceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomInterceptor extends AbstractInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(CustomInterceptor.class); + + public boolean handleRequest(Request rpcRequest) { + LOG.info("request intercepted, correlationId={}, service={}, method={}", + rpcRequest.getCorrelationId(), + rpcRequest.getTarget().getClass().getSimpleName(), + rpcRequest.getTargetMethod().getName()); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + LOG.info("around intercepted, before proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + + // invoke the interceptor list + chain.intercept(request, response); + + LOG.info("around intercepted, after proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + } + + public void handleResponse(Response response) { + if (response != null) { + LOG.info("reponse intercepted, correlationId={}, result={}", + response.getCorrelationId(), response.getResult()); + } + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java new file mode 100644 index 00000000..d6a02af2 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.example.springboot.api.EchoRequest; +import com.baidu.brpc.example.springboot.api.EchoResponse; + +import java.util.concurrent.Future; + +public interface EchoFacade { + EchoResponse echo(EchoRequest request); + EchoResponse echo2(EchoRequest request); + Future echo3(EchoRequest request); +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java new file mode 100644 index 00000000..41c1a612 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.example.springboot.api.AsyncEchoService; +import com.baidu.brpc.example.springboot.api.EchoRequest; +import com.baidu.brpc.example.springboot.api.EchoResponse; +import com.baidu.brpc.example.springboot.api.EchoService; +import com.baidu.brpc.spring.annotation.RpcProxy; +import lombok.Getter; +import lombok.Setter; +import org.springframework.stereotype.Service; + +import java.util.concurrent.Future; + +@Service +@Setter +@Getter +public class EchoFacadeImpl implements EchoFacade { + @RpcProxy + private EchoService echoService; + + @RpcProxy + private EchoService echoService2; + + @RpcProxy + private AsyncEchoService echoService3; + + public EchoResponse echo(EchoRequest request) { + System.out.println(echoService.hashCode()); + return echoService.echo(request); + } + + public EchoResponse echo2(EchoRequest request) { + System.out.println(echoService2.hashCode()); + return echoService2.echo(request); + } + + public Future echo3(EchoRequest request) { + System.out.println(echoService3.hashCode()); + Future future = echoService3.echo(request, new RpcCallback() { + @Override + public void success(EchoResponse response) { + System.out.println(response.getMessage()); + } + + @Override + public void fail(Throwable e) { + e.printStackTrace(); + } + }); + return future; + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java new file mode 100644 index 00000000..ee12b152 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.example.springboot.api.EchoRequest; +import com.baidu.brpc.example.springboot.api.EchoResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.concurrent.Future; + +@SpringBootApplication +@RestController +public class RpcClientTest { + @Autowired + private EchoFacade echoFacade; + + public static void main(String[] args) { + SpringApplication.run(RpcClientTest.class, args); + } + + @RequestMapping("/echo") + public String echo() { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + EchoResponse response = echoFacade.echo(request); + System.out.println(response.getMessage()); + + EchoResponse response2 = echoFacade.echo2(request); + System.out.println(response2.getMessage()); + + Future future = echoFacade.echo3(request); + try { + future.get(); + } catch (Exception ex) { + // ignore + } + + return response2.getMessage(); + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/application.yml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/application.yml new file mode 100644 index 00000000..690f1a1f --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: 8080 + +logging: + config: classpath:logback-spring.xml + directory: ./logs + +brpc: + global: + naming: + namingServiceUrl: zookeeper://127.0.0.1:2181/examples + group: "normal" + version: 2.0.0 + ignoreFailOfNamingService: false + client: + workThreadNum: 1 + ioThreadNum: 1 + interceptorBeanNames: customInterceptor + custom: + com.baidu.brpc.example.springboot.api.EchoService: + naming: + version: 2.0.0 + com.baidu.brpc.example.springboot.api.AsyncEchoService: + naming: + version: 2.0.0 \ No newline at end of file diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/logback-spring.xml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..0f19dce6 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-client/src/main/resources/logback-spring.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/client-all.%d{yyyy-MM-dd}.log + + 60 + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/client-warn.%d{yyyy-MM-dd}.log + + 120 + + + WARN + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + + + + + + + diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/pom.xml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/pom.xml new file mode 100644 index 00000000..371e1351 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/pom.xml @@ -0,0 +1,117 @@ + + + + 4.0.0 + + + com.baidu + brpc-spring-boot-examples + 2.5.9 + + + brpc-spring-boot-examples-server + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + + + + com.baidu + brpc-spring-boot-examples-api + ${project.version} + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + com.baidu + brpc-java-naming-zookeeper + + + org.springframework.boot + spring-boot-starter + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + ${project.name} + + + org.springframework.boot + spring-boot-maven-plugin + + com.baidu.brpc.example.springboot.server.RpcServerTest + + + + + repackage + + + + + + + + diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/BrpcConfigs.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/BrpcConfigs.java new file mode 100644 index 00000000..10e33517 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/BrpcConfigs.java @@ -0,0 +1,18 @@ +package com.baidu.brpc.example.springboot.server; + +import com.baidu.brpc.interceptor.Interceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BrpcConfigs { + @Bean + public Interceptor customInterceptor() { + return new CustomInterceptor(); + } + + @Bean + public Interceptor customInterceptor2() { + return new CustomInterceptor2(); + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor.java new file mode 100644 index 00000000..7aba1162 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.server; + +import com.baidu.brpc.interceptor.AbstractInterceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomInterceptor extends AbstractInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(CustomInterceptor.class); + + public boolean handleRequest(Request rpcRequest) { + LOG.info("request intercepted, correlationId={}, service={}, method={}", + rpcRequest.getCorrelationId(), + rpcRequest.getTarget().getClass().getSimpleName(), + rpcRequest.getTargetMethod().getName()); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + LOG.info("around intercepted, before proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + + // invoke the interceptor list + chain.intercept(request, response); + + LOG.info("around intercepted, after proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + } + + public void handleResponse(Response response) { + if (response != null) { + LOG.info("reponse intercepted, correlationId={}, result={}", + response.getCorrelationId(), response.getResult()); + } + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor2.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor2.java new file mode 100644 index 00000000..2e96d960 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/CustomInterceptor2.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.server; + +import com.baidu.brpc.interceptor.AbstractInterceptor; +import com.baidu.brpc.interceptor.InterceptorChain; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomInterceptor2 extends AbstractInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(CustomInterceptor2.class); + + public boolean handleRequest(Request rpcRequest) { + LOG.info("request intercepted by CustomInterceptor2, correlationId={}, service={}, method={}", + rpcRequest.getCorrelationId(), + rpcRequest.getTarget().getClass().getSimpleName(), + rpcRequest.getTargetMethod().getName()); + return true; + } + + @Override + public void aroundProcess(Request request, Response response, InterceptorChain chain) throws Exception { + LOG.info("around intercepted, before proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + + // invoke the interceptor list + chain.intercept(request, response); + + LOG.info("around intercepted, after proceed, correlationId={}, service={}, method={}", + request.getCorrelationId(), + request.getTarget().getClass().getSimpleName(), + request.getTargetMethod().getName()); + } + + public void handleResponse(Response response) { + if (response != null) { + LOG.info("reponse intercepted, correlationId={}, result={}", + response.getCorrelationId(), response.getResult()); + } + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/EchoServiceImpl.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/EchoServiceImpl.java new file mode 100644 index 00000000..ff0bac6e --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/EchoServiceImpl.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.server; + +import com.baidu.brpc.example.springboot.api.EchoRequest; +import com.baidu.brpc.example.springboot.api.EchoResponse; +import com.baidu.brpc.example.springboot.api.EchoService; +import com.baidu.brpc.spring.annotation.RpcExporter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RpcExporter +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/RpcServerTest.java b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/RpcServerTest.java new file mode 100644 index 00000000..2e06d019 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/java/com/baidu/brpc/example/springboot/server/RpcServerTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RpcServerTest { + public static void main(String[] args) { + SpringApplication application = new SpringApplication(RpcServerTest.class); + application.setWebApplicationType(WebApplicationType.NONE); + application.run(args); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + } + } + } +} diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/application.yml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/application.yml new file mode 100644 index 00000000..1d6ea67b --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/application.yml @@ -0,0 +1,19 @@ +logging: + config: classpath:logback-spring.xml + directory: ./logs + +brpc: + global: + naming: + namingServiceUrl: zookeeper://127.0.0.1:2181/examples + group: "normal" + version: 2.0.0 + ignoreFailOfNamingService: false + extra: + - key: weight + value: 10 + server: + port: 8002 + workThreadNum: 1 + ioThreadNum: 1 + interceptorBeanNames: customInterceptor,customInterceptor2 \ No newline at end of file diff --git a/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/logback-spring.xml b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..47f18f6c --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/brpc-spring-boot-examples-server/src/main/resources/logback-spring.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/server-all.%d{yyyy-MM-dd}.log + + 60 + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/server-warn.%d{yyyy-MM-dd}.log + + 120 + + + WARN + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + + + + + + + diff --git a/brpc-java-examples/brpc-spring-boot-examples/pom.xml b/brpc-java-examples/brpc-spring-boot-examples/pom.xml new file mode 100644 index 00000000..ccd58f47 --- /dev/null +++ b/brpc-java-examples/brpc-spring-boot-examples/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + + com.baidu + brpc-java-examples + 2.5.9 + + + brpc-spring-boot-examples + pom + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + brpc-spring-boot-examples-api + brpc-spring-boot-examples-server + brpc-spring-boot-examples-client + + + diff --git a/brpc-java-examples/pom.xml b/brpc-java-examples/pom.xml new file mode 100644 index 00000000..f0e0aef4 --- /dev/null +++ b/brpc-java-examples/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + + + com.baidu + brpc-java-parent + 2.5.9 + + + brpc-java-examples + pom + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + brpc-java-core-examples + brpc-spring-boot-examples + spring-cloud-brpc-examples + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/pom.xml b/brpc-java-examples/spring-cloud-brpc-examples/pom.xml new file mode 100644 index 00000000..64e1004d --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + + com.baidu + brpc-java-examples + 2.5.9 + + + spring-cloud-brpc-examples + pom + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + spring-cloud-brpc-examples-api + spring-cloud-brpc-examples-server + spring-cloud-brpc-examples-client + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/pom.xml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/pom.xml new file mode 100644 index 00000000..4d3eb8b8 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/pom.xml @@ -0,0 +1,78 @@ + + + + 4.0.0 + + + com.baidu + spring-cloud-brpc-examples + 2.5.9 + + + spring-cloud-brpc-examples-api + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + release + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + + + + com.baidu + brpc-java + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/AsyncEchoService.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/AsyncEchoService.java new file mode 100644 index 00000000..86b6d05b --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/AsyncEchoService.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.api; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.protocol.BrpcMeta; + +import java.util.concurrent.Future; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface AsyncEchoService extends EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + Future echo(EchoRequest request, RpcCallback callback); +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoRequest.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoRequest.java new file mode 100644 index 00000000..d9c3ee46 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoResponse.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoResponse.java new file mode 100644 index 00000000..3cba16f1 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.api; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoService.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoService.java new file mode 100644 index 00000000..ded4b02b --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-api/src/main/java/com/baidu/brpc/example/springcloud/api/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.api; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/pom.xml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/pom.xml new file mode 100644 index 00000000..783dd5ea --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/pom.xml @@ -0,0 +1,140 @@ + + + + 4.0.0 + + + com.baidu + spring-cloud-brpc-examples + 2.5.9 + + + spring-cloud-brpc-examples-client + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + release + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + + + + com.baidu + spring-cloud-brpc-examples-api + ${project.version} + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + com.baidu + spring-cloud-brpc + ${project.version} + + + com.baidu + brpc-java-naming-zookeeper + + + org.springframework.boot + spring-boot-starter-web + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + ${project.name} + + + org.springframework.boot + spring-boot-maven-plugin + + com.baidu.brpc.example.springboot.client.RpcClientTest + + + + + repackage + + + + + + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java new file mode 100644 index 00000000..8f9ed96f --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacade.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + + +import com.baidu.brpc.example.springcloud.api.EchoRequest; +import com.baidu.brpc.example.springcloud.api.EchoResponse; + +import java.util.concurrent.Future; + +public interface EchoFacade { + EchoResponse echo(EchoRequest request); + EchoResponse echo2(EchoRequest request); + Future echo3(EchoRequest request); +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java new file mode 100644 index 00000000..feab2e52 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/EchoFacadeImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.client.RpcCallback; +import com.baidu.brpc.example.springcloud.api.AsyncEchoService; +import com.baidu.brpc.example.springcloud.api.EchoRequest; +import com.baidu.brpc.example.springcloud.api.EchoResponse; +import com.baidu.brpc.example.springcloud.api.EchoService; +import com.baidu.brpc.spring.annotation.RpcProxy; +import lombok.Getter; +import lombok.Setter; +import org.springframework.stereotype.Service; + +import java.util.concurrent.Future; + +@Service +@Setter +@Getter +public class EchoFacadeImpl implements EchoFacade { + @RpcProxy(name = "brpc-example-server") + private EchoService echoService; + + @RpcProxy(name = "brpc-example-server") + private EchoService echoService2; + + @RpcProxy(name = "brpc-example-server") + private AsyncEchoService echoService3; + + public EchoResponse echo(EchoRequest request) { + System.out.println(echoService.hashCode()); + return echoService.echo(request); + } + + public EchoResponse echo2(EchoRequest request) { + System.out.println(echoService2.hashCode()); + return echoService2.echo(request); + } + + public Future echo3(EchoRequest request) { + System.out.println(echoService3.hashCode()); + Future future = echoService3.echo(request, new RpcCallback() { + @Override + public void success(EchoResponse response) { + System.out.println(response.getMessage()); + } + + @Override + public void fail(Throwable e) { + e.printStackTrace(); + } + }); + return future; + } +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java new file mode 100644 index 00000000..a53a227b --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/java/com/baidu/brpc/example/springboot/client/RpcClientTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springboot.client; + +import com.baidu.brpc.example.springcloud.api.EchoRequest; +import com.baidu.brpc.example.springcloud.api.EchoResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.concurrent.Future; + +@SpringBootApplication +@RestController +public class RpcClientTest { + @Autowired + private EchoFacade echoFacade; + + public static void main(String[] args) { + SpringApplication.run(RpcClientTest.class, args); + } + + @RequestMapping("/echo") + public String echo() { + EchoRequest request = new EchoRequest(); + request.setMessage("hello"); + EchoResponse response = echoFacade.echo(request); + System.out.println(response.getMessage()); + + EchoResponse response2 = echoFacade.echo2(request); + System.out.println(response2.getMessage()); + + Future future = echoFacade.echo3(request); + try { + future.get(); + } catch (Exception ex) { + // ignore + } + + return response2.getMessage(); + } +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/application.yml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/application.yml new file mode 100644 index 00000000..a4d24a2e --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/application.yml @@ -0,0 +1,27 @@ +server: + port: 8080 + +spring: + application: + name: brpc-example-client + +eureka: + client: + serviceUrl: + defaultZone: http://${spring.cloud.client.ip-address}:8889/eureka/,http://127.0.0.1:8890/eureka/ + fetch-registry: true + registry-fetch-interval-seconds: 30 + +management: + security: + enabled: false + +logging: + config: classpath:logback-spring.xml + directory: ./logs + +brpc: + global: + client: + workThreadNum: 1 + ioThreadNum: 1 \ No newline at end of file diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/logback-spring.xml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..0f19dce6 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-client/src/main/resources/logback-spring.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/client-all.%d{yyyy-MM-dd}.log + + 60 + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/client-warn.%d{yyyy-MM-dd}.log + + 120 + + + WARN + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + + + + + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/pom.xml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/pom.xml new file mode 100644 index 00000000..7d9de11b --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/pom.xml @@ -0,0 +1,129 @@ + + + + 4.0.0 + + + com.baidu + spring-cloud-brpc-examples + 2.5.9 + + + spring-cloud-brpc-examples-server + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.5.RELEASE + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + Greenwich.SR1 + pom + import + + + + + + + com.baidu + spring-cloud-brpc-examples-api + ${project.version} + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + com.baidu + spring-cloud-brpc + ${project.version} + + + com.baidu + brpc-java-naming-zookeeper + + + org.springframework.boot + spring-boot-starter + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.25 + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + ${project.name} + + + org.springframework.boot + spring-boot-maven-plugin + + com.baidu.brpc.example.springboot.server.RpcServerTest + + + + + repackage + + + + + + + + diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/EchoServiceImpl.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/EchoServiceImpl.java new file mode 100644 index 00000000..86bcbfc0 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/EchoServiceImpl.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.server; + +import com.baidu.brpc.example.springcloud.api.EchoRequest; +import com.baidu.brpc.example.springcloud.api.EchoResponse; +import com.baidu.brpc.example.springcloud.api.EchoService; +import com.baidu.brpc.spring.annotation.RpcExporter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RpcExporter +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/RpcServerTest.java b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/RpcServerTest.java new file mode 100644 index 00000000..12d99dfd --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/java/com/baidu/brpc/example/springcloud/server/RpcServerTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.example.springcloud.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class RpcServerTest { + public static void main(String[] args) { + SpringApplication application = new SpringApplication(RpcServerTest.class); + application.run(args); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + } + } + } +} diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/application.yml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/application.yml new file mode 100644 index 00000000..c36ec9f6 --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/application.yml @@ -0,0 +1,28 @@ +server: + port: 8881 + +spring: + application: + name: brpc-example-server + +eureka: + client: + serviceUrl: + defaultZone: http://${spring.cloud.client.ip-address}:8889/eureka/,http://127.0.0.1:8890/eureka/ + fetch-registry: true + registry-fetch-interval-seconds: 30 + +management: + security: + enabled: false + +logging: + config: classpath:logback-spring.xml + directory: ./logs + +brpc: + global: + server: + port: 8002 + workThreadNum: 1 + ioThreadNum: 1 \ No newline at end of file diff --git a/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/logback-spring.xml b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..47f18f6c --- /dev/null +++ b/brpc-java-examples/spring-cloud-brpc-examples/spring-cloud-brpc-examples-server/src/main/resources/logback-spring.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/server-all.%d{yyyy-MM-dd}.log + + 60 + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + ${logDirectory}/server-warn.%d{yyyy-MM-dd}.log + + 120 + + + WARN + + + %date [%thread] %-5level %logger{80} - %msg%n + UTF-8 + + + + + + + + + + + + diff --git a/brpc-java-naming-consul/pom.xml b/brpc-java-naming-consul/pom.xml new file mode 100644 index 00000000..282a30e9 --- /dev/null +++ b/brpc-java-naming-consul/pom.xml @@ -0,0 +1,63 @@ + + 4.0.0 + + + com.baidu + brpc-java-parent + 2.5.9 + + + brpc-java-naming-consul + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + com.baidu + brpc-java + + + com.ecwid.consul + consul-api + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.projectlombok + lombok + provided + + + com.pszymczyk.consul + embedded-consul + test + + + org.apache.logging.log4j + log4j-core + test + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + diff --git a/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingFactory.java b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingFactory.java new file mode 100644 index 00000000..215bad6d --- /dev/null +++ b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul; + +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; + +public class ConsulNamingFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "consul"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + return new ConsulNamingService(url); + } +} diff --git a/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingService.java b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingService.java new file mode 100644 index 00000000..416769ab --- /dev/null +++ b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/ConsulNamingService.java @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.naming.*; +import com.baidu.brpc.naming.consul.model.ConsulConstants; +import com.baidu.brpc.naming.consul.model.ConsulResponse; +import com.baidu.brpc.naming.consul.model.ConsulService; +import com.baidu.brpc.utils.CustomThreadFactory; +import com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.QueryParams; +import com.ecwid.consul.v1.Response; +import com.ecwid.consul.v1.agent.model.NewService; +import com.ecwid.consul.v1.health.model.HealthService; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import io.netty.util.internal.ConcurrentSet; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Collection; +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.Executors; + +@Slf4j +public class ConsulNamingService implements NamingService { + + private BrpcURL url; + private ConsulClient client; + private int retryInterval; + private int consulInterval; + private int lookupInterval; + private ConcurrentSet failedRegisters = + new ConcurrentSet(); + private ConcurrentSet failedUnregisters = + new ConcurrentSet(); + + private ConcurrentMap failedSubscribes = + new ConcurrentHashMap(); + private ConcurrentSet failedUnsubscribes = + new ConcurrentSet(); + + private Timer timer; + + private final ConcurrentMap lookupGroupServices = new ConcurrentHashMap(); + + private Set serviceIds = new ConcurrentSet(); + private ScheduledExecutorService heartbeatExecutor; + + private ConcurrentHashMap consulLookupFuture = new ConcurrentHashMap(); + + private ConcurrentHashMap>> serviceCache + = new ConcurrentHashMap>>(); + + public ConsulNamingService(BrpcURL url) { + this.url = url; + try { + String[] hostPorts = url.getHostPorts().split(":"); + this.client = new ConsulClient(hostPorts[0], Integer.parseInt(hostPorts[1])); + } catch (Exception e) { + throw new RpcException(RpcException.SERVICE_EXCEPTION, + "wrong configuration of url, should be like test.bj:port", e); + } + + this.retryInterval = url.getIntParameter(Constants.INTERVAL, Constants.DEFAULT_INTERVAL); + this.consulInterval = url.getIntParameter(ConsulConstants.CONSULINTERVAL, + ConsulConstants.DEFAULT_CONSUL_INTERVAL); + this.lookupInterval = url.getIntParameter(ConsulConstants.LOOKUPINTERVAL, + ConsulConstants.DEFAULT_LOOKUP_INTERVAL); + timer = new HashedWheelTimer(new CustomThreadFactory("consul-retry-timer-thread")); + + timer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + try { + for (RegisterInfo registerInfo : failedRegisters) { + register(registerInfo); + } + for (RegisterInfo registerInfo : failedUnregisters) { + unregister(registerInfo); + } + for (Map.Entry entry : failedSubscribes.entrySet()) { + subscribe(entry.getKey(), entry.getValue()); + } + for (SubscribeInfo subscribeInfo : failedUnsubscribes) { + unsubscribe(subscribeInfo); + } + } catch (Exception ex) { + log.warn("retry timer exception:", ex); + } + timer.newTimeout(this, retryInterval, TimeUnit.MILLISECONDS); + } + }, + retryInterval, TimeUnit.MILLISECONDS); + + heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(); + + heartbeatExecutor.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + for (String tempService : serviceIds) { + client.agentCheckPass(tempService); + log.debug("Sending consul heartbeat for: {}", tempService); + } + } + }, ConsulConstants.HEARTBEAT_CIRCLE, + ConsulConstants.HEARTBEAT_CIRCLE, TimeUnit.MILLISECONDS); + } + + public void destroy() { + serviceIds.clear(); + timer.stop(); + heartbeatExecutor.shutdown(); + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + + List instances = new ArrayList(); + + try { + ConcurrentHashMap> serviceUpdate + = lookupServiceUpdate(subscribeInfo.getGroup()); + + if (!serviceUpdate.isEmpty() && serviceUpdate.containsKey(subscribeInfo.getInterfaceName())) { + instances = serviceUpdate.get(subscribeInfo.getInterfaceName()); + } + } catch (Exception ex) { + log.warn("lookup end point list failed from {}, msg={}", + url, ex.getMessage()); + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("lookup end point list failed from consul failed", ex); + } + } + + return instances; + } + + @Override public void subscribe(final SubscribeInfo subscribeInfo, final NotifyListener listener) { + + final String path = getSubscribePath(subscribeInfo); + + Future future = heartbeatExecutor.scheduleAtFixedRate( + new Runnable() { + @Override + public void run() { + try { + long time = System.currentTimeMillis(); + log.debug("heart beat schedule, time: {}", + time); + Map> instanceForGroup + = serviceCache.get(subscribeInfo.getGroup()); + List currentInstances = lookup(subscribeInfo); + + ConcurrentHashMap> serviceUpdate = lookupServiceUpdate( + subscribeInfo.getGroup()); + + updateServiceCache(subscribeInfo.getGroup() + , serviceUpdate); + + log.debug("heart beat schedule, lookup and " + + "update time: {}", + System.currentTimeMillis() - time); + + if ((instanceForGroup != null && !instanceForGroup.isEmpty()) + || !currentInstances.isEmpty()) { + List lastInstances = new ArrayList(); + if (instanceForGroup != null) { + lastInstances = instanceForGroup.get(subscribeInfo.getInterfaceName()); + } + + Collection addList = CollectionUtils.subtract( + currentInstances, lastInstances); + Collection deleteList = CollectionUtils.subtract( + lastInstances, currentInstances); + listener.notify(addList, deleteList); + + failedSubscribes.remove(subscribeInfo); + } + log.info("subscribe success from {}", url); + } catch (Exception e) { + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("subscribe " + + "failed from " + url, e); + } else { + failedSubscribes.putIfAbsent(subscribeInfo, listener); + } + } + } + + }, ConsulConstants.HEARTBEAT_CIRCLE, + ConsulConstants.DEFAULT_LOOKUP_INTERVAL, TimeUnit.MILLISECONDS); + + consulLookupFuture.putIfAbsent(path, future); + } + + @Override public void unsubscribe(SubscribeInfo subscribeInfo) { + try { + + String path = getSubscribePath(subscribeInfo); + consulLookupFuture.get(path).cancel(false); + + log.info("unsubscribe success from {}", url); + } catch (Exception ex) { + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("unsubscribe failed from " + url, ex); + } else { + failedUnsubscribes.add(subscribeInfo); + return; + } + } + } + + public String getSubscribePath(SubscribeInfo subscribeInfo) { + return subscribeInfo.getGroup() + "-" + subscribeInfo.getInterfaceName() + "-" + subscribeInfo.getVersion(); + } + + @Override public void register(RegisterInfo registerInfo) { + try { + + NewService newService = getConsulNewService(registerInfo); + client.agentServiceRegister(newService); + + serviceIds.add("service:" + newService.getId()); + + log.info("register success to {}", url); + } catch (Exception ex) { + if (!registerInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("Failed to register to " + url, ex); + } else { + failedRegisters.add(registerInfo); + return; + } + } + failedRegisters.remove(registerInfo); + } + + @Override public void unregister(RegisterInfo registerInfo) { + try { + NewService newService = getConsulNewService(registerInfo); + client.agentServiceDeregister(newService.getId()); + + serviceIds.remove("service:" + newService.getId()); + } catch (Exception ex) { + if (!registerInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("Failed to unregister to " + url, ex); + } else { + failedUnregisters.add(registerInfo); + return; + } + } + failedUnregisters.remove(registerInfo); + } + + private NewService getConsulNewService(RegisterInfo registerInfo) { + NewService newService = new NewService(); + newService.setName(registerInfo.getGroup()); + newService.setId(getRegisterPath(registerInfo)); + newService.setAddress(registerInfo.getHost()); + newService.setPort(registerInfo.getPort()); + newService.setTags(Arrays.asList(registerInfo.getGroup(), registerInfo.getInterfaceName())); + NewService.Check check = new NewService.Check(); + check.setTtl(this.consulInterval + "s"); + check.setDeregisterCriticalServiceAfter("3m"); + + newService.setCheck(check); + + return newService; + } + + public String getRegisterPath(RegisterInfo registerInfo) { + StringBuilder sb = new StringBuilder(); + sb.append(registerInfo.getHost()).append(":").append(registerInfo.getPort()).append("-") + .append(registerInfo.getInterfaceName()); + return sb.toString(); + + } + + private void updateServiceCache(String group, ConcurrentHashMap> groupUrls) { + if (groupUrls != null && !groupUrls.isEmpty()) { + ConcurrentHashMap> groupMap = serviceCache.get(group); + if (groupMap == null) { + serviceCache.put(group, groupUrls); + } + for (Map.Entry> entry : groupUrls.entrySet()) { + if (groupMap != null) { + groupMap.put(entry.getKey(), entry.getValue()); + } + } + } + } + + private ConcurrentHashMap> lookupServiceUpdate(String group) { + ConcurrentHashMap> groupUrls + = new ConcurrentHashMap>(); + Long lastConsulIndexId = lookupGroupServices.get(group) == null ? 0 : lookupGroupServices.get(group); + + long time = System.currentTimeMillis(); + + ConsulResponse> response = lookupConsulService(group, lastConsulIndexId); + log.debug("lookupConsulService, time: {}", System.currentTimeMillis() - time); + + if (response != null) { + List services = response.getValue(); + if (services != null && !services.isEmpty() + && response.getConsulIndex() > lastConsulIndexId) { + for (ConsulService service : services) { + try { + String serviceName = ""; + List tags = service.getTags(); + for (String tag : tags) { + if (!tag.equals(service.getName())) { + serviceName = tag; + } + } + List urlList = groupUrls.get(serviceName); + + if (urlList == null) { + urlList = new ArrayList(); + } + urlList.add(new ServiceInstance(service.getAddress(), service.getPort())); + groupUrls.put(serviceName, urlList); + } catch (Exception e) { + } + + } + lookupGroupServices.put(group, response.getConsulIndex()); + return groupUrls; + } else { + } + } + return groupUrls; + } + + private ConsulResponse> lookupConsulService(String serviceName, Long lastConsulIndexId) { + ConsulResponse> response = lookupHealthService( + serviceName, + lastConsulIndexId); + return response; + } + + public ConsulResponse> lookupHealthService( + String serviceName, long lastConsulIndex) { + QueryParams queryParams = new QueryParams( + ConsulConstants.CONSUL_BLOCK_TIME_SECONDS, lastConsulIndex); + Response> orgResponse = client.getHealthServices( + serviceName, true, queryParams); + ConsulResponse> newResponse = null; + if (orgResponse != null && orgResponse.getValue() != null + && !orgResponse.getValue().isEmpty()) { + List HealthServices = orgResponse.getValue(); + List ConsulServices = new ArrayList( + HealthServices.size()); + + for (HealthService orgService : HealthServices) { + try { + ConsulService newService = convertToConsulService(orgService); + ConsulServices.add(newService); + } catch (Exception e) { + String servcieid = "null"; + if (orgService.getService() != null) { + servcieid = orgService.getService().getId(); + } + log.info("Consul lookup health service error, service id:{}", servcieid); + } + } + if (!ConsulServices.isEmpty()) { + newResponse = new ConsulResponse>(); + newResponse.setValue(ConsulServices); + newResponse.setConsulIndex(orgResponse.getConsulIndex()); + newResponse.setConsulLastContact(orgResponse + .getConsulLastContact()); + newResponse.setConsulKnownLeader(orgResponse + .isConsulKnownLeader()); + } + } + + return newResponse; + } + + private ConsulService convertToConsulService(HealthService healthService) { + ConsulService service = new ConsulService(); + HealthService.Service org = healthService.getService(); + service.setAddress(org.getAddress()); + service.setId(org.getId()); + service.setName(org.getService()); + service.setPort(org.getPort()); + service.setTags(org.getTags()); + return service; + } + +} diff --git a/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulConstants.java b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulConstants.java new file mode 100644 index 00000000..79f78419 --- /dev/null +++ b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulConstants.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul.model; + +public class ConsulConstants { + + public static final int DEFAULT_CONSUL_INTERVAL = 30; + + public static final String CONSULINTERVAL = "consulInterval"; + + public static final String LOOKUPINTERVAL = "lookupInterval"; + + /** + * Time To Live, in seconds. Every service will register a ttl for health check. + */ + public static final int TTL = 30; + /** + * consul block time for query params, measures in minutes. + */ + public static final int CONSUL_BLOCK_TIME_MINUTES = 10; + + /** + * consul block time for query params, measures in seconds. + */ + public static final long CONSUL_BLOCK_TIME_SECONDS = CONSUL_BLOCK_TIME_MINUTES * 60; + + /** + * heartbeat cycle time + */ + public static final int HEARTBEAT_CIRCLE = 2000; + + /** + * default check time for consul service + */ + public static final int DEFAULT_LOOKUP_INTERVAL = 20000; +} diff --git a/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulResponse.java b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulResponse.java new file mode 100644 index 00000000..6eacce4a --- /dev/null +++ b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulResponse.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul.model; + +public class ConsulResponse { + + /** + * details return from consul + */ + private T value; + + private Long consulIndex; + + private Boolean consulKnownLeader; + + private Long consulLastContact; + + public T getValue() { + return value; + } + + public void setValue(T value) { + this.value = value; + } + + public Long getConsulIndex() { + return consulIndex; + } + + public void setConsulIndex(Long consulIndex) { + this.consulIndex = consulIndex; + } + + public Boolean getConsulKnownLeader() { + return consulKnownLeader; + } + + public void setConsulKnownLeader(Boolean consulKnownLeader) { + this.consulKnownLeader = consulKnownLeader; + } + + public Long getConsulLastContact() { + return consulLastContact; + } + + public void setConsulLastContact(Long consulLastContact) { + this.consulLastContact = consulLastContact; + } + +} diff --git a/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulService.java b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulService.java new file mode 100644 index 00000000..bae22614 --- /dev/null +++ b/brpc-java-naming-consul/src/main/java/com/baidu/brpc/naming/consul/model/ConsulService.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul.model; + +import java.util.List; + +public class ConsulService { + + private String id; + + private String name; + + private List tags; + + private String address; + + private Integer port; + + private long ttl; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public long getTtl() { + return ttl; + } + + public void setTtl(long ttl) { + this.ttl = ttl; + } + +} diff --git a/brpc-java-naming-consul/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory b/brpc-java-naming-consul/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory new file mode 100644 index 00000000..de205ca5 --- /dev/null +++ b/brpc-java-naming-consul/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory @@ -0,0 +1 @@ +com.baidu.brpc.naming.consul.ConsulNamingFactory diff --git a/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/ConsulNamingServiceTest.java b/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/ConsulNamingServiceTest.java new file mode 100644 index 00000000..e11fbc0d --- /dev/null +++ b/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/ConsulNamingServiceTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.naming.SubscribeInfo; +import com.pszymczyk.consul.ConsulProcess; +import com.pszymczyk.consul.ConsulStarterBuilder; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import java.util.Collection; +import java.util.List; + +@Slf4j +public class ConsulNamingServiceTest { + + private static BrpcURL namingUrl; + private static ConsulNamingService consulNamingService; + private static ConsulProcess consul; + + @BeforeClass + public static void setUp() throws Exception { + final String customConfiguration = + "{\n" + + " \"datacenter\": \"dc-test\",\n" + + " \"log_level\": \"info\"\n" + + "}\n"; + consul = ConsulStarterBuilder.consulStarter() + .withConsulVersion("1.2.1") + .withCustomConfig(customConfiguration) + .build() + .start(); + namingUrl = new BrpcURL("consul://127.0.0.1:" + consul.getHttpPort()); + consulNamingService = new ConsulNamingService(namingUrl); + } + + @AfterClass + public static void tearDown() throws Exception { + consulNamingService.destroy(); + consul.close(); + consulNamingService = null; + } + + protected RegisterInfo createRegisterInfo(String host, int port) { + RegisterInfo registerInfo = new RegisterInfo(); + registerInfo.setHost(host); + registerInfo.setPort(port); + registerInfo.setInterfaceName(EchoService.class.getName()); + return registerInfo; + } + + protected SubscribeInfo createSubscribeInfo(boolean ignoreFail) { + SubscribeInfo subscribeInfo = new SubscribeInfo(); + subscribeInfo.setInterfaceName(EchoService.class.getName()); + subscribeInfo.setIgnoreFailOfNamingService(ignoreFail); + return subscribeInfo; + } + + @Test + public void testRegisterAndSubscribe() throws InterruptedException { + + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8015); + RegisterInfo anotherRegisterInfo = createRegisterInfo("127.0.0.1", 8016); + consulNamingService.register(registerInfo); + consulNamingService.register(anotherRegisterInfo); + SubscribeInfo subscribeInfo = createSubscribeInfo(false); + Thread.sleep(10 * 1000); + + consulNamingService.subscribe(subscribeInfo, new NotifyListener() { + @Override public void notify(Collection addList, + Collection deleteList) { + log.info("notify: {}, {}", addList, deleteList); + } + }); + + Thread.sleep(10 * 1000); + consulNamingService.unregister(registerInfo); + Thread.sleep(50 * 1000); + + } + + @Test + public void testLookup() throws InterruptedException { + SubscribeInfo subscribeInfo = createSubscribeInfo(true); + List instances = consulNamingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 0); + + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8012); + consulNamingService.register(registerInfo); + Thread.sleep(10 * 1000); + + instances = consulNamingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 1); + Assert.assertTrue(instances.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(instances.get(0).getPort() == 8012); + consulNamingService.unregister(registerInfo); + + } + +} diff --git a/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/EchoService.java b/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/EchoService.java new file mode 100644 index 00000000..69f66dc8 --- /dev/null +++ b/brpc-java-naming-consul/src/test/java/com/baidu/brpc/naming/consul/EchoService.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.consul; + +public interface EchoService { + String echo(String request); +} diff --git a/brpc-java-naming-consul/src/test/resources/log4j2.xml b/brpc-java-naming-consul/src/test/resources/log4j2.xml new file mode 100644 index 00000000..54e5ef34 --- /dev/null +++ b/brpc-java-naming-consul/src/test/resources/log4j2.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + diff --git a/brpc-java-naming-zookeeper/pom.xml b/brpc-java-naming-zookeeper/pom.xml new file mode 100644 index 00000000..2104eff2 --- /dev/null +++ b/brpc-java-naming-zookeeper/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + + + com.baidu + brpc-java-parent + 2.5.9 + + + brpc-java-naming-zookeeper + jar + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + + + + + com.baidu + brpc-java + + + org.apache.curator + curator-framework + + + org.apache.curator + curator-recipes + + + org.projectlombok + lombok + provided + + + org.apache.curator + curator-test + test + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + diff --git a/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateNamingFactory.java b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateNamingFactory.java new file mode 100644 index 00000000..ab167858 --- /dev/null +++ b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateNamingFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming.zookeeper; + +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; + +public class StargateNamingFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "star"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + return new StargateZookeeperNamingService(url); + } +} diff --git a/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateZookeeperNamingService.java b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateZookeeperNamingService.java new file mode 100644 index 00000000..3b781ff5 --- /dev/null +++ b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/StargateZookeeperNamingService.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming.zookeeper; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.protocol.stargate.StargateConstants; +import com.baidu.brpc.protocol.stargate.StargateURI; + +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.extern.slf4j.Slf4j; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.PathChildrenCache; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; +import org.apache.zookeeper.CreateMode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Stargate注册时,serviceName 为全小写 + */ +@Slf4j +public class StargateZookeeperNamingService extends ZookeeperNamingService { + private static final String DEFAULT_VERSION = "1.0.0"; + private static final String DEFAULT_GROUP = "normal"; + private static final Set IGNORED_EXTRA_KEYS = new HashSet(); + private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); + + static { + IGNORED_EXTRA_KEYS.add(StargateConstants.GROUP_KEY); + IGNORED_EXTRA_KEYS.add(StargateConstants.VERSION_KEY); + IGNORED_EXTRA_KEYS.add(StargateConstants.INTERFACE_KEY); + IGNORED_EXTRA_KEYS.add(StargateConstants.INTERFACE_SIMPLE_KEY); + } + + public StargateZookeeperNamingService(BrpcURL url) { + super(url); + } + + @Override + public List lookup(SubscribeInfo info) { + String path = buildParentNodePath(resolveGroup(info), info.getInterfaceName(), resolveVersion(info)); + List instances = new ArrayList(); + try { + List childList = client.getChildren().forPath(path); + for (String child : childList) { + // 跨过所有客户端节点 + if (StargateConstants.ZK_CONSUMER_DIR.equals(child)) { + continue; + } + String childPath = path + "/" + child; + try { + String childData = new String(client.getData().forPath(childPath)); + StargateURI uri = new StargateURI.Builder(childData).build(); + instances.add(new ServiceInstance(uri.getHost(), uri.getPort())); + } catch (Exception getDataFailedException) { + log.warn("get child data failed, path:{}, ex:", childPath, getDataFailedException); + } + } + log.info("lookup {} instances from {}", instances.size(), url); + } catch (Exception ex) { + log.warn("lookup service instance list failed from {}, msg={}", + url, ex.getMessage()); + if (!info.isIgnoreFailOfNamingService()) { + throw new RpcException("lookup end point list failed from zookeeper failed", ex); + } + } + return instances; + } + + @Override + public void subscribe(SubscribeInfo info, final NotifyListener listener) { + try { + final String path = buildParentNodePath(resolveGroup(info), info.getInterfaceName(), resolveVersion(info)); + PathChildrenCache cache = new PathChildrenCache(client, path, true); + cache.getListenable().addListener(new PathChildrenCacheListener() { + @Override + public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { + ChildData data = event.getData(); + // 子节点信息,将监听的父节点信息擦除 + String childNodePath = data.getPath().replace(path + "/", ""); + // 如果是客户端上线,不做处理 + if (StargateConstants.ZK_CONSUMER_DIR.equals(childNodePath)) { + return; + } + switch (event.getType()) { + case CHILD_ADDED: { + ServiceInstance endPoint = new ServiceInstance(childNodePath); + listener.notify(Collections.singletonList(endPoint), + Collections.emptyList()); + break; + } + case CHILD_REMOVED: { + ServiceInstance endPoint = new ServiceInstance(childNodePath); + listener.notify(Collections.emptyList(), + Collections.singletonList(endPoint)); + break; + } + case CHILD_UPDATED: + default: + break; + } + } + }); + cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + failedSubscribes.remove(info); + subscribeCacheMap.putIfAbsent(info, cache); + log.info("stargate subscribe success from {}", url); + } catch (Exception ex) { + if (!info.isIgnoreFailOfNamingService()) { + throw new RpcException("stargate subscribe failed from " + url, ex); + } else { + failedSubscribes.putIfAbsent(info, listener); + } + } + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + super.unsubscribe(subscribeInfo); + } + + @Override + public void register(RegisterInfo info) { + String parentPath = buildParentNodePath(resolveGroup(info), info.getInterfaceName(), resolveVersion(info)); + String path = parentPath + "/" + info.getHost() + ":" + info.getPort(); + String pathData = buildStarRegisterPathData(info); + try { + if (client.checkExists().forPath(parentPath) == null) { + client.create().withMode(CreateMode.PERSISTENT).forPath(parentPath); + } + if (client.checkExists().forPath(path) != null) { + try { + client.delete().forPath(path); + } catch (Exception deleteException) { + log.info("zk delete node failed, ignore"); + } + } + client.create().withMode(CreateMode.EPHEMERAL).forPath(path, pathData.getBytes()); + log.info("stargate register success to {}", url); + } catch (Exception ex) { + if (!info.isIgnoreFailOfNamingService()) { + throw new RpcException("stargate Failed to register to " + url, ex); + } else { + failedRegisters.add(info); + return; + } + } + failedRegisters.remove(info); + } + + @Override + public void unregister(RegisterInfo info) { + String parentPath = buildParentNodePath(resolveGroup(info), info.getInterfaceName(), resolveVersion(info)); + String path = "/" + info.getHost() + ":" + info.getPort(); + try { + client.delete().guaranteed().forPath(parentPath + path); + log.info("stargate unregister success to {}", url); + } catch (Exception ex) { + if (!info.isIgnoreFailOfNamingService()) { + throw new RpcException("stargate Failed to unregister from " + url, ex); + } else { + failedUnregisters.add(info); + } + } + } + + /** + * stargate 注册或者订阅节点时,整个 Path 为小写 + */ + private String buildParentNodePath(String group, String serviceName, String version) { + return ("/" + group + ":" + serviceName + ":" + version).toLowerCase(); + } + + + /** + * Build the path data for registration. + *

+ * Stargate protocol requires the data to be a JSON String containing + * a URI with the following scheme: + * "star://127.0.0.1:8002? + * group=normal + * &interface=com.baidu.brpc.example.stargate.stargatedemoservice + * &version=1.0.0" + */ + private String buildStarRegisterPathData(RegisterInfo registerInfo) { + Map extraOptions = registerInfo.getExtra(); + String group = resolveGroup(registerInfo); + String version = resolveVersion(registerInfo); + StargateURI.Builder builder = new StargateURI.Builder("star", registerInfo.getHost(), registerInfo.getPort()); + builder.param(StargateConstants.GROUP_KEY, group); + builder.param(StargateConstants.VERSION_KEY, version); + builder.param(StargateConstants.INTERFACE_KEY, registerInfo.getInterfaceName()); + if (extraOptions != null) { + for (Map.Entry entry : extraOptions.entrySet()) { + if (IGNORED_EXTRA_KEYS.contains(entry.getKey())) { + continue; + } + builder.param(entry.getKey(), entry.getValue()); + } + } + String uriString = builder.build().toString(); + return GSON.toJson(uriString); + } + + private String resolveGroup(NamingOptions info) { + if (Strings.isNullOrEmpty(info.getGroup())) { + return DEFAULT_GROUP; + } + return info.getGroup(); + } + + private String resolveVersion(NamingOptions info) { + if (Strings.isNullOrEmpty(info.getVersion())) { + return DEFAULT_VERSION; + } + return info.getVersion(); + } + +} diff --git a/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingFactory.java b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingFactory.java new file mode 100644 index 00000000..177deb0b --- /dev/null +++ b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.zookeeper; + +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; + +public class ZookeeperNamingFactory implements NamingServiceFactory { + + @Override + public String getName() { + return "zookeeper"; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + return new ZookeeperNamingService(url); + } +} diff --git a/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingService.java b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingService.java new file mode 100644 index 00000000..a63dff63 --- /dev/null +++ b/brpc-java-naming-zookeeper/src/main/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingService.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.naming.zookeeper; + +import com.baidu.brpc.client.instance.Endpoint; +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.exceptions.RpcException; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.Constants; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.utils.CustomThreadFactory; +import com.baidu.brpc.utils.GsonUtils; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import io.netty.util.internal.ConcurrentSet; +import lombok.extern.slf4j.Slf4j; +import org.apache.curator.RetryPolicy; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.PathChildrenCache; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.CreateMode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +@Slf4j +public class ZookeeperNamingService implements NamingService { + protected BrpcURL url; + protected CuratorFramework client; + private int retryInterval; + private Timer timer; + protected ConcurrentSet failedRegisters = + new ConcurrentSet(); + protected ConcurrentSet failedUnregisters = + new ConcurrentSet(); + protected ConcurrentMap failedSubscribes = + new ConcurrentHashMap(); + protected ConcurrentSet failedUnsubscribes = + new ConcurrentSet(); + protected ConcurrentMap subscribeCacheMap = + new ConcurrentHashMap(); + + public ZookeeperNamingService(BrpcURL url) { + this.url = url; + int sleepTimeoutMs = url.getIntParameter( + Constants.SLEEP_TIME_MS, Constants.DEFAULT_SLEEP_TIME_MS); + int maxTryTimes = url.getIntParameter( + Constants.MAX_TRY_TIMES, Constants.DEFAULT_MAX_TRY_TIMES); + int sessionTimeoutMs = url.getIntParameter( + Constants.SESSION_TIMEOUT_MS, Constants.DEFAULT_SESSION_TIMEOUT_MS); + int connectTimeoutMs = url.getIntParameter( + Constants.CONNECT_TIMEOUT_MS, Constants.DEFAULT_CONNECT_TIMEOUT_MS); + String namespace = Constants.DEFAULT_PATH; + if (url.getPath().startsWith("/")) { + namespace = url.getPath().substring(1); + } + RetryPolicy retryPolicy = new ExponentialBackoffRetry(sleepTimeoutMs, maxTryTimes); + client = CuratorFrameworkFactory.builder() + .connectString(url.getHostPorts()) + .connectionTimeoutMs(connectTimeoutMs) + .sessionTimeoutMs(sessionTimeoutMs) + .retryPolicy(retryPolicy) + .namespace(namespace) + .build(); + client.start(); + + this.retryInterval = url.getIntParameter(Constants.INTERVAL, Constants.DEFAULT_INTERVAL); + timer = new HashedWheelTimer(new CustomThreadFactory("zookeeper-retry-timer-thread")); + timer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + try { + for (RegisterInfo registerInfo : failedRegisters) { + register(registerInfo); + } + for (RegisterInfo registerInfo : failedUnregisters) { + unregister(registerInfo); + } + for (Map.Entry entry : failedSubscribes.entrySet()) { + subscribe(entry.getKey(), entry.getValue()); + } + for (SubscribeInfo subscribeInfo : failedUnsubscribes) { + unsubscribe(subscribeInfo); + } + } catch (Exception ex) { + log.warn("retry timer exception:", ex); + } + timer.newTimeout(this, retryInterval, TimeUnit.MILLISECONDS); + } + }, + retryInterval, TimeUnit.MILLISECONDS); + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + String path = getSubscribePath(subscribeInfo); + List instances = new ArrayList(); + try { + List childList = client.getChildren().forPath(path); + for (String child : childList) { + String childPath = path + "/" + child; + try { + String childData = new String(client.getData().forPath(childPath)); + Endpoint endpoint = GsonUtils.fromJson(childData, Endpoint.class); + instances.add(new ServiceInstance(endpoint)); + } catch (Exception getDataFailedException) { + log.warn("get child data failed, path:{}, ex:", childPath, getDataFailedException); + } + } + log.info("lookup {} instances from {}", instances.size(), url); + } catch (Exception ex) { + log.warn("lookup end point list failed from {}, msg={}", + url, ex.getMessage()); + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("lookup end point list failed from zookeeper failed", ex); + } + } + return instances; + } + + @Override + public void subscribe(SubscribeInfo subscribeInfo, final NotifyListener listener) { + try { + String path = getSubscribePath(subscribeInfo); + PathChildrenCache cache = new PathChildrenCache(client, path, true); + cache.getListenable().addListener(new PathChildrenCacheListener() { + @Override + public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { + ChildData data = event.getData(); + switch (event.getType()) { + case CHILD_ADDED: { + ServiceInstance instance = GsonUtils.fromJson( + new String(data.getData()), ServiceInstance.class); + listener.notify(Collections.singletonList(instance), + Collections.emptyList()); + break; + } + case CHILD_REMOVED: { + ServiceInstance instance = GsonUtils.fromJson( + new String(data.getData()), ServiceInstance.class); + listener.notify(Collections.emptyList(), + Collections.singletonList(instance)); + break; + } + case CHILD_UPDATED: + break; + default: + break; + } + } + }); + cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + failedSubscribes.remove(subscribeInfo); + subscribeCacheMap.putIfAbsent(subscribeInfo, cache); + log.info("subscribe success from {}", url); + } catch (Exception ex) { + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("subscribe failed from " + url, ex); + } else { + failedSubscribes.putIfAbsent(subscribeInfo, listener); + } + } + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + PathChildrenCache cache = subscribeCacheMap.get(subscribeInfo); + try { + if (cache != null) { + cache.close(); + } + log.info("unsubscribe success from {}", url); + } catch (Exception ex) { + if (!subscribeInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("unsubscribe failed from " + url, ex); + } else { + failedUnsubscribes.add(subscribeInfo); + return; + } + } + subscribeCacheMap.remove(subscribeInfo); + } + + @Override + public void register(RegisterInfo registerInfo) { + String parentPath = getParentRegisterPath(registerInfo); + String path = getRegisterPath(registerInfo); + String pathData = getRegisterPathData(registerInfo); + try { + if (client.checkExists().forPath(parentPath) == null) { + client.create().withMode(CreateMode.PERSISTENT).forPath(parentPath); + } + if (client.checkExists().forPath(path) != null) { + try { + client.delete().forPath(path); + } catch (Exception deleteException) { + log.info("zk delete node failed, ignore"); + } + } + client.create().withMode(CreateMode.EPHEMERAL).forPath(path, pathData.getBytes()); + log.info("register success to {}", url); + } catch (Exception ex) { + if (!registerInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("Failed to register to " + url, ex); + } else { + failedRegisters.add(registerInfo); + return; + } + } + failedRegisters.remove(registerInfo); + } + + @Override + public void unregister(RegisterInfo registerInfo) { + String path = getRegisterPath(registerInfo); + try { + client.delete().guaranteed().forPath(path); + log.info("unregister success to {}", url); + } catch (Exception ex) { + if (!registerInfo.isIgnoreFailOfNamingService()) { + throw new RpcException("Failed to unregister from " + url, ex); + } else { + failedUnregisters.add(registerInfo); + } + } + } + + public String getSubscribePath(SubscribeInfo subscribeInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("/"); + sb.append(subscribeInfo.getGroup()).append(":"); + sb.append(subscribeInfo.getInterfaceName()).append(":"); + sb.append(subscribeInfo.getVersion()); + String path = sb.toString(); + return path; + } + + public String getParentRegisterPath(RegisterInfo registerInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("/"); + sb.append(registerInfo.getGroup()).append(":"); + sb.append(registerInfo.getInterfaceName()).append(":"); + sb.append(registerInfo.getVersion()); + String path = sb.toString(); + return path; + } + + public String getRegisterPath(RegisterInfo registerInfo) { + StringBuilder sb = new StringBuilder(); + sb.append(getParentRegisterPath(registerInfo)); + sb.append("/"); + sb.append(registerInfo.getHost()).append(":").append(registerInfo.getPort()); + String path = sb.toString(); + return path; + } + + public String getRegisterPathData(RegisterInfo registerInfo) { + Endpoint endPoint = new Endpoint(registerInfo.getHost(), registerInfo.getPort()); + return GsonUtils.toJson(endPoint); + } +} diff --git a/brpc-java-naming-zookeeper/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory b/brpc-java-naming-zookeeper/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory new file mode 100644 index 00000000..f14ed0d2 --- /dev/null +++ b/brpc-java-naming-zookeeper/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory @@ -0,0 +1,2 @@ +com.baidu.brpc.naming.zookeeper.ZookeeperNamingFactory +com.baidu.brpc.naming.zookeeper.StargateNamingFactory \ No newline at end of file diff --git a/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/EchoService.java b/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/EchoService.java new file mode 100644 index 00000000..9f1bafe6 --- /dev/null +++ b/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/EchoService.java @@ -0,0 +1,5 @@ +package com.baidu.brpc.naming.zookeeper; + +public interface EchoService { + String echo(String request); +} diff --git a/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingServiceTest.java b/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingServiceTest.java new file mode 100644 index 00000000..21121f0d --- /dev/null +++ b/brpc-java-naming-zookeeper/src/test/java/com/baidu/brpc/naming/zookeeper/ZookeeperNamingServiceTest.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.naming.zookeeper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.curator.test.TestingServer; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.naming.SubscribeInfo; + +public class ZookeeperNamingServiceTest { + private TestingServer zkServer; + private BrpcURL namingUrl; + private ZookeeperNamingService namingService; + + public void setUp() throws Exception { + zkServer = new TestingServer(2087, true); + namingUrl = new BrpcURL("zookeeper://127.0.0.1:2087"); + namingService = new ZookeeperNamingService(namingUrl); + } + + public void tearDown() throws Exception { + zkServer.stop(); + } + + protected RegisterInfo createRegisterInfo(String host, int port) { + RegisterInfo registerInfo = new RegisterInfo(); + registerInfo.setHost(host); + registerInfo.setPort(port); + registerInfo.setInterfaceName(EchoService.class.getName()); + return registerInfo; + } + + protected SubscribeInfo createSubscribeInfo(boolean ignoreFail) { + SubscribeInfo subscribeInfo = new SubscribeInfo(); + subscribeInfo.setInterfaceName(EchoService.class.getName()); + subscribeInfo.setIgnoreFailOfNamingService(ignoreFail); + return subscribeInfo; + } + + @Test + public void testLookup() throws Exception { + setUp(); + SubscribeInfo subscribeInfo = createSubscribeInfo(true); + List instances = namingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 0); + + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8012); + namingService.register(registerInfo); + instances = namingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 1); + Assert.assertTrue(instances.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(instances.get(0).getPort() == 8012); + namingService.unregister(registerInfo); + tearDown(); + } + + @Test + public void testSubscribe() throws Exception { + setUp(); + final List adds = new ArrayList(); + final List deletes = new ArrayList(); + SubscribeInfo subscribeInfo = createSubscribeInfo(false); + namingService.subscribe(subscribeInfo, new NotifyListener() { + @Override + public void notify(Collection addList, Collection deleteList) { + System.out.println("receive new subscribe info time:" + System.currentTimeMillis()); + System.out.println("add size:" + addList.size()); + for (ServiceInstance instance : addList) { + System.out.println(instance); + } + adds.addAll(addList); + + System.out.println("delete size:" + deleteList.size()); + for (ServiceInstance instance : deleteList) { + System.out.println(instance); + } + deletes.addAll(deleteList); + } + }); + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8013); + namingService.register(registerInfo); + System.out.println("register time=" + System.currentTimeMillis()); + Thread.sleep(1000); + Assert.assertTrue(adds.size() == 1); + Assert.assertTrue(deletes.size() == 0); + Assert.assertTrue(adds.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(adds.get(0).getPort() == 8013); + adds.clear(); + deletes.clear(); + + namingService.unregister(registerInfo); + System.out.println("unregister time=" + System.currentTimeMillis()); + Thread.sleep(1000); + Assert.assertTrue(adds.size() == 0); + Assert.assertTrue(deletes.size() == 1); + Assert.assertTrue(deletes.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(deletes.get(0).getPort() == 8013); + + namingService.unsubscribe(subscribeInfo); + tearDown(); + } + + /** + * This test must test under actual zookeeper server, Not the TestingServer of Curator + */ + @Test + @Ignore + public void testSubscribeWhenZookeeperDownAndUp() throws Exception { + namingUrl = new BrpcURL("zookeeper://127.0.0.1:2181"); + namingService = new ZookeeperNamingService(namingUrl); + + final List adds = new ArrayList(); + final List deletes = new ArrayList(); + SubscribeInfo subscribeInfo = createSubscribeInfo(false); + namingService.subscribe(subscribeInfo, new NotifyListener() { + @Override + public void notify(Collection addList, Collection deleteList) { + System.out.println("receive new subscribe info time:" + System.currentTimeMillis()); + System.out.println("add size:" + addList.size()); + for (ServiceInstance instance : addList) { + System.out.println(instance); + } + adds.addAll(addList); + + System.out.println("delete size:" + deleteList.size()); + for (ServiceInstance instance : deleteList) { + System.out.println(instance); + } + deletes.addAll(deleteList); + } + }); + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8014); + namingService.register(registerInfo); + System.out.println("register time=" + System.currentTimeMillis()); + Thread.sleep(1000); + Assert.assertTrue(adds.size() == 1); + Assert.assertTrue(deletes.size() == 0); + Assert.assertTrue(adds.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(adds.get(0).getPort() == 8014); + adds.clear(); + deletes.clear(); + + // sleep for restarting zookeeper + Thread.sleep(30 * 1000); + + List instances = namingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 1); + Assert.assertTrue(instances.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(instances.get(0).getPort() == 8014); + + namingService.unregister(registerInfo); + System.out.println("unregister time=" + System.currentTimeMillis()); + Thread.sleep(1000); + Assert.assertTrue(adds.size() == 0); + Assert.assertTrue(deletes.size() == 1); + Assert.assertTrue(deletes.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(deletes.get(0).getPort() == 8014); + + namingService.unsubscribe(subscribeInfo); + } + + /** + * This test must test under actual zookeeper server, Not the TestingServer of Curator + */ + @Test + @Ignore + public void testRegisterWhenZookeeperDownAndUp() throws Exception { + namingUrl = new BrpcURL("zookeeper://127.0.0.1:2181"); + namingService = new ZookeeperNamingService(namingUrl); + + RegisterInfo registerInfo = createRegisterInfo("127.0.0.1", 8015); + namingService.register(registerInfo); + SubscribeInfo subscribeInfo = createSubscribeInfo(false); + List instances = namingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 1); + Assert.assertTrue(instances.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(instances.get(0).getPort() == 8015); + + // sleep for restarting zookeeper + Thread.sleep(30 * 1000); + instances = namingService.lookup(subscribeInfo); + Assert.assertTrue(instances.size() == 1); + System.out.println(instances.get(0)); + Assert.assertTrue(instances.get(0).getIp().equals("127.0.0.1")); + Assert.assertTrue(instances.get(0).getPort() == 8015); + namingService.unregister(registerInfo); + } +} diff --git a/brpc-java-naming-zookeeper/src/test/resources/log4j2.xml b/brpc-java-naming-zookeeper/src/test/resources/log4j2.xml new file mode 100644 index 00000000..d026221c --- /dev/null +++ b/brpc-java-naming-zookeeper/src/test/resources/log4j2.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/brpc-spring-boot-starter/pom.xml b/brpc-spring-boot-starter/pom.xml new file mode 100644 index 00000000..51655d5a --- /dev/null +++ b/brpc-spring-boot-starter/pom.xml @@ -0,0 +1,103 @@ + + + + 4.0.0 + + com.baidu + brpc-java-parent + 2.5.9 + + brpc-spring-boot-starter + jar + ${project.artifactId} + The module for Spring extendsion + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + true + + + + package + + jar + + + + com/baidu/brpc/** + + + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + + + + com.baidu + brpc-spring + + + org.springframework.boot + spring-boot-autoconfigure + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/AbstractRegister.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/AbstractRegister.java new file mode 100644 index 00000000..5339143c --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/AbstractRegister.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.boot.autoconfigure.AutoConfigurationPackages; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; + +import java.util.Collection; + +public abstract class AbstractRegister implements ResourceLoaderAware, EnvironmentAware, BeanFactoryAware { + protected BeanFactory beanFactory; + protected ResourceLoader resourceLoader; + protected Environment environment; + + protected Class getClass(String beanClassName) { + try { + return Class.forName(beanClassName); + } catch (ClassNotFoundException e) { + throw new BeanInitializationException("error create bean with class: " + beanClassName, e); + } + } + + protected Collection getBasePackages() { + return AutoConfigurationPackages.get(beanFactory); + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BeanPostProcessorRegister.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BeanPostProcessorRegister.java new file mode 100644 index 00000000..4b1174a0 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BeanPostProcessorRegister.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure; + +import com.baidu.brpc.spring.annotation.CommonAnnotationBeanPostProcessor; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; + +/** + * register {@link CommonAnnotationBeanPostProcessor} with ImportBeanDefinitionRegistrar, + * instead of AutoConfigure class, so that CommonAnnotationBeanPostProcessor can be init before other beans. + */ +public class BeanPostProcessorRegister implements ImportBeanDefinitionRegistrar { + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); + beanDefinition.setBeanClass(CommonAnnotationBeanPostProcessor.class); + beanDefinition.setSynthetic(true); + MutablePropertyValues values = new MutablePropertyValues(); + values.addPropertyValue("callback", new SpringBootAnnotationResolver()); + beanDefinition.setPropertyValues(values); + registry.registerBeanDefinition("commonAnnotationBeanPostProcessor", beanDefinition); + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcApplicationContextUtils.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcApplicationContextUtils.java new file mode 100644 index 00000000..4e8889dc --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcApplicationContextUtils.java @@ -0,0 +1,51 @@ +package com.baidu.brpc.spring.boot.autoconfigure; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; + +public class BrpcApplicationContextUtils implements ApplicationContextAware, PriorityOrdered { + + private static ApplicationContext applicationContext; + + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE + 1; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + BrpcApplicationContextUtils.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + checkApplicationContext(); + return applicationContext; + } + + @SuppressWarnings("unchecked") + public static T getBean(String name) { + checkApplicationContext(); + return (T) applicationContext.getBean(name); + } + + @SuppressWarnings("unchecked") + public static T getBean(Class c) { + checkApplicationContext(); + return applicationContext.getBean(c); + } + + @SuppressWarnings("unchecked") + public static T getBean(String name, Class c) { + checkApplicationContext(); + return (T) applicationContext.getBean(name, c); + } + + private static void checkApplicationContext() { + if (applicationContext == null) { + throw new IllegalStateException("applicationContext ia null"); + } + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcAutoConfiguration.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcAutoConfiguration.java new file mode 100644 index 00000000..d0b2042e --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/BrpcAutoConfiguration.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure; + +import com.baidu.brpc.spring.boot.autoconfigure.config.BrpcProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@EnableConfigurationProperties(BrpcProperties.class) +@Configuration +@Import({BeanPostProcessorRegister.class, RpcExporterRegister.class}) +public class BrpcAutoConfiguration { + + @Bean + public BrpcApplicationContextUtils brpcApplicationContextUtils() { + return new BrpcApplicationContextUtils(); + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/RpcExporterRegister.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/RpcExporterRegister.java new file mode 100644 index 00000000..2d7f750a --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/RpcExporterRegister.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure; + +import com.baidu.brpc.spring.annotation.RpcExporter; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.autoconfigure.AutoConfigurationPackages; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.util.ClassUtils; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +public class RpcExporterRegister extends AbstractRegister implements ImportBeanDefinitionRegistrar { + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + Map serviceExporterMap = new HashMap<>(); + AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); + Collection candidates = getCandidates(resourceLoader); + for (BeanDefinition candidate : candidates) { + Class clazz = getClass(candidate.getBeanClassName()); + Class[] interfaces = ClassUtils.getAllInterfacesForClass(clazz); + if (interfaces.length != 1) { + throw new BeanInitializationException("bean interface num must equal 1, " + clazz.getName()); + } + String serviceBeanName = beanNameGenerator.generateBeanName(candidate, registry); + String old = serviceExporterMap.putIfAbsent(interfaces[0], serviceBeanName); + if (old != null) { + throw new RuntimeException("interface already be exported by bean name:" + old); + } + registry.registerBeanDefinition(serviceBeanName, candidate); + } + } + + private Collection getCandidates(ResourceLoader resourceLoader) { + ClassPathScanningCandidateComponentProvider scanner = + new ClassPathScanningCandidateComponentProvider(false, environment); + + scanner.addIncludeFilter(new AnnotationTypeFilter(RpcExporter.class)); + scanner.setResourceLoader(resourceLoader); + return AutoConfigurationPackages.get(beanFactory).stream() + .flatMap(basePackage -> scanner.findCandidateComponents(basePackage).stream()) + .collect(Collectors.toSet()); + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/SpringBootAnnotationResolver.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/SpringBootAnnotationResolver.java new file mode 100644 index 00000000..3ee6ec3e --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/SpringBootAnnotationResolver.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure; + +import com.baidu.bjf.remoting.protobuf.utils.JDKCompilerHelper; +import com.baidu.bjf.remoting.protobuf.utils.compiler.Compiler; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.spring.RpcProxyFactoryBean; +import com.baidu.brpc.spring.RpcServiceExporter; +import com.baidu.brpc.spring.annotation.AbstractAnnotationParserCallback; +import com.baidu.brpc.spring.annotation.RpcAnnotationResolverListener; +import com.baidu.brpc.spring.annotation.RpcExporter; +import com.baidu.brpc.spring.annotation.RpcProxy; +import com.baidu.brpc.spring.boot.autoconfigure.config.BrpcConfig; +import com.baidu.brpc.spring.boot.autoconfigure.config.BrpcProperties; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; +import org.springframework.util.ClassUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Supports annotation resolver for {@link RpcProxy} and {@link RpcExporter} under springboot. + * + * @author huwenwei + */ +@Setter +@Getter +@Slf4j +public class SpringBootAnnotationResolver extends AbstractAnnotationParserCallback + implements InitializingBean, PriorityOrdered { + /** + * properties from spring boot application.yml + */ + private BrpcProperties brpcProperties; + + /** + * The rpc clients. + */ + private List rpcClients = new ArrayList(); + + /** + * The port mapping exporters. + */ + private Map portMappingExporters = new HashMap(); + + /** + * The compiler. + */ + private Compiler compiler; + + /** + * status to control start only once. + */ + private AtomicBoolean started = new AtomicBoolean(false); + + /* the default naming service url */ + private String namingServiceUrl; + + /** + * The default registry center service for all service + */ + private NamingServiceFactory namingServiceFactory; + + /** + * The default interceptors for all service + */ +// private List interceptors; + + /** + * The protobuf rpc annotation resolver listener. + */ + private RpcAnnotationResolverListener protobufRpcAnnotationResolverListener; + + private int order = Ordered.LOWEST_PRECEDENCE - 3; + + @Override + public Object annotationAtField(Annotation t, Object value, String beanName, PropertyValues pvs, + DefaultListableBeanFactory beanFactory, Field field) throws BeansException { + if (t instanceof RpcProxy) { + try { + log.info("Annotation 'BrpcProxy' on field '" + field.getName() + "' for target '" + beanName + + "' created"); + return parseRpcProxyAnnotation((RpcProxy) t, field.getType(), beanFactory); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + return value; + } + + @Override + public Object annotationAtMethod(Annotation t, Object bean, String beanName, PropertyValues pvs, + DefaultListableBeanFactory beanFactory, Method method) throws BeansException { + if (t instanceof RpcProxy) { + try { + log.info("Annotation 'BrpcProxy' on method '" + method.getName() + "' for target '" + beanName + + "' created"); + return parseRpcProxyAnnotation((RpcProxy) t, method.getParameterTypes()[0], beanFactory); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + return null; + } + + @Override + public Object annotationAtType(Annotation t, Object bean, String beanName, + ConfigurableListableBeanFactory beanFactory) throws BeansException { + if (t instanceof RpcExporter) { + log.info("Annotation 'RpcExporter' for target '" + beanName + "' created"); + parseRpcExporterAnnotation((RpcExporter) t, beanFactory, beanFactory.getBean(beanName)); + } + return bean; + } + + @Override + public void annotationAtTypeAfterStarted(Annotation t, Object bean, String beanName, + ConfigurableListableBeanFactory beanFactory) throws BeansException { + if (started.compareAndSet(false, true)) { + // do export service here + Collection values = portMappingExporters.values(); + for (RpcServiceExporter rpcServiceExporter : values) { + try { + rpcServiceExporter.afterPropertiesSet(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + } + + @Override + public void destroy() throws Exception { + if (rpcClients != null) { + for (RpcProxyFactoryBean bean : rpcClients) { + try { + bean.destroy(); + } catch (Exception e) { + log.error(e.getMessage(), e.getCause()); + } + } + } + + if (portMappingExporters != null) { + Collection exporters = portMappingExporters.values(); + for (RpcServiceExporter rpcServiceExporter : exporters) { + try { + rpcServiceExporter.destroy(); + } catch (Exception e) { + log.error(e.getMessage(), e.getCause()); + } + } + } + + if (protobufRpcAnnotationResolverListener != null) { + protobufRpcAnnotationResolverListener.destroy(); + } + + } + + @Override + public Class getTypeAnnotation() { + return RpcExporter.class; + } + + @Override + public List> getMethodFieldAnnotation() { + List> list = new ArrayList>(); + list.add(RpcProxy.class); + return list; + } + + @Override + public void afterPropertiesSet() throws Exception { + if (compiler != null) { + JDKCompilerHelper.setCompiler(compiler); + } + } + + @Override + public int getOrder() { + return order; + } + + /** + * Sets the compiler. + * + * @param compiler the new compiler + */ + public void setCompiler(Compiler compiler) { + this.compiler = compiler; + } + + /** + * Parses the {@link RpcExporter} annotation. + * + * @param rpcExporter the rpc exporter + * @param beanFactory the bean factory + * @param bean the bean + */ + private void parseRpcExporterAnnotation(RpcExporter rpcExporter, + ConfigurableListableBeanFactory beanFactory, + Object bean) { + Class serviceClass = AopUtils.getTargetClass(bean); + Class[] interfaces = ClassUtils.getAllInterfacesForClass(serviceClass); + if (interfaces.length != 1) { + throw new RuntimeException("service interface num must equal 1, " + serviceClass.getName()); + } + Class serviceInterface = interfaces[0]; + BrpcConfig brpcConfig = getServiceConfig(beanFactory, serviceInterface); + + // if there are multi service on one port, the first service configs effect only. + Integer port = brpcConfig.getServer().getPort(); + RpcServiceExporter rpcServiceExporter = portMappingExporters.get(port); + if (rpcServiceExporter == null) { + rpcServiceExporter = new RpcServiceExporter(); + portMappingExporters.put(port, rpcServiceExporter); + rpcServiceExporter.setServicePort(port); + rpcServiceExporter.copyFrom(brpcConfig.getServer()); + if (brpcConfig.getNaming() != null) { + rpcServiceExporter.setNamingServiceUrl(brpcConfig.getNaming().getNamingServiceUrl()); + } + } + + // interceptor + if (brpcConfig.getServer() != null + && StringUtils.isNoneBlank(brpcConfig.getServer().getInterceptorBeanNames())) { + String[] interceptorNameArray = brpcConfig.getServer().getInterceptorBeanNames().split(","); + for (String interceptorBeanName : interceptorNameArray) { + Interceptor interceptor = beanFactory.getBean(interceptorBeanName, Interceptor.class); + if (!rpcServiceExporter.getInterceptors().contains(interceptor)) { + rpcServiceExporter.getInterceptors().add(interceptor); + } + } + } + + // naming options + rpcServiceExporter.getServiceNamingOptions().put(bean, brpcConfig.getNaming()); + + if (brpcConfig.getServer() != null && brpcConfig.getServer().isUseSharedThreadPool()) { + rpcServiceExporter.getCustomOptionsServiceMap().put(brpcConfig.getServer(), bean); + } else { + rpcServiceExporter.getRegisterServices().add(bean); + } + + if (protobufRpcAnnotationResolverListener != null) { + protobufRpcAnnotationResolverListener.onRpcExporterAnnotationParsered( + rpcExporter, port, bean, rpcServiceExporter.getRegisterServices()); + } + } + + /** + * Parses the rpc proxy annotation. + * + * @param rpcProxy the rpc proxy + * @param beanFactory the bean factory + * @return the object + * @throws Exception the exception + */ + private Object parseRpcProxyAnnotation(RpcProxy rpcProxy, + Class serviceInterface, + DefaultListableBeanFactory beanFactory) throws Exception { + RpcProxyFactoryBean rpcProxyFactoryBean; + String factoryBeanName = "&" + serviceInterface.getSimpleName(); + try { + rpcProxyFactoryBean = beanFactory.getBean(factoryBeanName, RpcProxyFactoryBean.class); + if (rpcProxyFactoryBean != null) { + return rpcProxyFactoryBean.getObject(); + } + } catch (NoSuchBeanDefinitionException ex) { + // continue the following logic to create new factory bean + } + + rpcProxyFactoryBean = createRpcProxyFactoryBean(rpcProxy, beanFactory, serviceInterface); + rpcClients.add(rpcProxyFactoryBean); + Object object = rpcProxyFactoryBean.getObject(); + if (protobufRpcAnnotationResolverListener != null) { + protobufRpcAnnotationResolverListener.onRpcProxyAnnotationParsed(rpcProxy, rpcProxyFactoryBean, + rpcProxyFactoryBean.getObject()); + } + + return object; + } + + /** + * Creates the rpc proxy factory bean. + * + * @return the rpc proxy factory bean + */ + private RpcProxyFactoryBean createRpcProxyFactoryBean(RpcProxy rpcProxy, + DefaultListableBeanFactory beanFactory, + Class serviceInterface) { + GenericBeanDefinition beanDef = new GenericBeanDefinition(); + beanDef.setBeanClass(RpcProxyFactoryBean.class); + beanDef.setDependsOn("brpcApplicationContextUtils"); + MutablePropertyValues values = new MutablePropertyValues(); + BrpcConfig brpcConfig = getServiceConfig(beanFactory, serviceInterface); + for (Field field : RpcClientOptions.class.getDeclaredFields()) { + try { + field.setAccessible(true); + values.addPropertyValue(field.getName(), field.get(brpcConfig.getClient())); + } catch (Exception ex) { + log.warn("field not exist:", ex); + } + } + values.addPropertyValue("serviceInterface", serviceInterface); + values.addPropertyValue("serviceId", rpcProxy.name()); + if (brpcConfig.getNaming() != null) { + values.addPropertyValue("namingServiceUrl", brpcConfig.getNaming().getNamingServiceUrl()); + values.addPropertyValue("group", brpcConfig.getNaming().getGroup()); + values.addPropertyValue("version", brpcConfig.getNaming().getVersion()); + values.addPropertyValue("ignoreFailOfNamingService", + brpcConfig.getNaming().isIgnoreFailOfNamingService()); + } + + // interceptor + String interceptorNames = brpcConfig.getClient().getInterceptorBeanNames(); + if (!StringUtils.isBlank(interceptorNames)) { + List customInterceptors = new ArrayList<>(); + String[] interceptorNameArray = interceptorNames.split(","); + for (String interceptorBeanName : interceptorNameArray) { + Interceptor interceptor = beanFactory.getBean(interceptorBeanName, Interceptor.class); + customInterceptors.add(interceptor); + } + values.addPropertyValue("interceptors", Arrays.asList(customInterceptors)); + } + + beanDef.setPropertyValues(values); + String serviceInterfaceBeanName = serviceInterface.getSimpleName(); + beanFactory.registerBeanDefinition(serviceInterfaceBeanName, beanDef); + return beanFactory.getBean("&" + serviceInterfaceBeanName, RpcProxyFactoryBean.class); + } + + private BrpcConfig getServiceConfig(ListableBeanFactory beanFactory, Class serviceInterface) { + if (brpcProperties == null) { + brpcProperties = beanFactory.getBean(BrpcProperties.class); + if (brpcProperties == null) { + throw new RuntimeException("bean of BrpcProperties is null"); + } + } + return brpcProperties.getServiceConfig(serviceInterface); + } + +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcConfig.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcConfig.java new file mode 100644 index 00000000..2c9c1512 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +@Getter +@Setter +public class BrpcConfig { + /** + * Naming config + */ + @NestedConfigurationProperty + private RpcNamingConfig naming; + /** + * Client Config + */ + @NestedConfigurationProperty + private RpcClientConfig client; + /** + * Server config + */ + @NestedConfigurationProperty + private RpcServerConfig server; + + public BrpcConfig() { + } + + public BrpcConfig(BrpcConfig rhs) { + if (rhs.getNaming() != null) { + this.naming = new RpcNamingConfig(rhs.getNaming()); + } + if (rhs.getClient() != null) { + this.client = new RpcClientConfig(rhs.getClient()); + } + if (rhs.getServer() != null) { + this.server = new RpcServerConfig(rhs.getServer()); + } + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcProperties.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcProperties.java new file mode 100644 index 00000000..3c086a8a --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/BrpcProperties.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure.config; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; + +import java.util.HashMap; +import java.util.Map; + +/** + * BRPC Configuration. + *

+ * Global defaults can be set under `brpc.global`. + * Service-specific configs can be set under `brpc.custom.fully-qualified-service-name`. + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "brpc") +public class BrpcProperties implements EnvironmentAware { + @NestedConfigurationProperty + private BrpcConfig global; + @Setter + private Environment environment; + + private static String camelToKebabCase(String str) { + return str.replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(); + } + + private static void rewriteMap(Map map) { + if (map == null) { + return; + } + Map ret = new HashMap<>(); + for (int i = 0; i < map.size() / 2; i++) { + String key = map.remove(i + ".key"); + String value = map.remove(i + ".value"); + if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) { + break; + } + ret.put(key, value); + } + map.clear(); + map.putAll(ret); + } + + public BrpcConfig getServiceConfig(Class serviceInterface) { + BrpcConfig brpcConfig = new BrpcConfig(global); + if (brpcConfig.getClient() == null) { + brpcConfig.setClient(new RpcClientConfig()); + } + if (brpcConfig.getServer() == null) { + brpcConfig.setServer(new RpcServerConfig()); + } + if (brpcConfig.getNaming() == null) { + brpcConfig.setNaming(new RpcNamingConfig()); + } + String prefix = "brpc.custom." + serviceInterface.getName() + "."; + Binder binder = Binder.get(environment); + binder.bind(camelToKebabCase(prefix + "client"), Bindable.ofInstance(brpcConfig.getClient())); + binder.bind(camelToKebabCase(prefix + "server"), Bindable.ofInstance(brpcConfig.getServer())); + binder.bind(camelToKebabCase(prefix + "naming"), Bindable.ofInstance(brpcConfig.getNaming())); + rewriteMap(brpcConfig.getNaming().getExtra()); + return brpcConfig; + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcClientConfig.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcClientConfig.java new file mode 100644 index 00000000..43d0a405 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcClientConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure.config; + +import com.baidu.brpc.client.RpcClientOptions; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class RpcClientConfig extends RpcClientOptions { + private String interceptorBeanNames; + + public RpcClientConfig() { + } + + public RpcClientConfig(RpcClientConfig rhs) { + super(rhs); + this.interceptorBeanNames = rhs.getInterceptorBeanNames(); + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcNamingConfig.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcNamingConfig.java new file mode 100644 index 00000000..782618bb --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcNamingConfig.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure.config; + +import com.baidu.brpc.naming.NamingOptions; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RpcNamingConfig extends NamingOptions { + + private String namingServiceUrl; + + public RpcNamingConfig() { + } + + public RpcNamingConfig(RpcNamingConfig rhs) { + super(rhs); + this.namingServiceUrl = rhs.getNamingServiceUrl(); + } +} diff --git a/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcServerConfig.java b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcServerConfig.java new file mode 100644 index 00000000..425b1f15 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/java/com/baidu/brpc/spring/boot/autoconfigure/config/RpcServerConfig.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.boot.autoconfigure.config; + +import com.baidu.brpc.server.RpcServerOptions; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class RpcServerConfig extends RpcServerOptions { + private int port; + private boolean useSharedThreadPool; + private String interceptorBeanNames; + + public RpcServerConfig() { + } + + public RpcServerConfig(RpcServerConfig rhs) { + super(rhs); + this.port = rhs.getPort(); + this.useSharedThreadPool = rhs.isUseSharedThreadPool(); + this.interceptorBeanNames = rhs.getInterceptorBeanNames(); + } +} diff --git a/brpc-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/brpc-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..637e3419 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,22 @@ +{ + "properties": [ + { + "name": "brpc.custom", + "type": "java.util.Map", + "description": "Service specific customized config." + } + ], + "hints": [ + { + "name": "brpc.global.server.interceptor-bean-name", + "providers": [ + { + "name": "spring-bean-reference", + "parameters": { + "target": "com.baidu.brpc.interceptor.Interceptor" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/brpc-spring-boot-starter/src/main/resources/META-INF/spring.factories b/brpc-spring-boot-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..88e868c9 --- /dev/null +++ b/brpc-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.baidu.brpc.spring.boot.autoconfigure.BrpcAutoConfiguration \ No newline at end of file diff --git a/brpc-spring/pom.xml b/brpc-spring/pom.xml new file mode 100644 index 00000000..e0bdd611 --- /dev/null +++ b/brpc-spring/pom.xml @@ -0,0 +1,83 @@ + + + + 4.0.0 + + com.baidu + brpc-java-parent + 2.5.9 + + brpc-spring + jar + ${project.artifactId} + The module for Spring extendsion + + + UTF-8 + 3.2.11.RELEASE + + + + + + + com.baidu + brpc-java + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + cglib + cglib + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test + + + diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolved.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolved.java new file mode 100644 index 00000000..51b67f54 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolved.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +/** + * Placehoader resolved call back . + * + * @author xiemalin + * @since 2.17 + */ +public interface PlaceholderResolved { + + /** + * parsed placeholder value returned. + * + * @param placeholder the placeholder + * @return parsed string + */ + String doResolved(String placeholder); +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolver.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolver.java new file mode 100644 index 00000000..3e4112d4 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/PlaceholderResolver.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import org.apache.commons.lang3.StringUtils; + +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * 字符串占位符解析工作类.
+ * 例如: String testStr = "abc${ab}" 如果ab="ddd",则解析后结果为 abcddd
+ *

+ * example:
+ *     public static void main(String[] args) {
+        final Map placeholderVals = new HashMap(5);
+        placeholderVals.put("key1", "china");
+        placeholderVals.put("key2", "3");
+        placeholderVals.put("key3", "beijin");
+        
+        String testStr = "hello ${key1}";
+        
+        PlaceholderResolver resolver = new PlaceholderResolver(new PlaceholderResolved() {
+            
+            public String doResolved(String placeholder) {
+                System.out.println("find placeholder:" + placeholder);
+                return placeholderVals.get(placeholder);
+            }
+        });
+        resolver.setPlaceholderPrefix("${");
+        resolver.setPlaceholderSuffix("}");
+        
+        System.out.println(resolver.doParse(testStr));
+        
+        testStr = "hello ${key${key2}}";
+        System.out.println(resolver.doParse(testStr));
+    }
+    
+ * + * @author xiemalin + * @since 2.17 + */ +public class PlaceholderResolver { + + /** Logger for this class. */ + private static final Logger LOGGER = Logger + .getLogger(PlaceholderResolver.class.getName()); + + /** Default placeholder prefix: "${". */ + public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; + + /** Default placeholder suffix: "}". */ + public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; + + /** placeholder prefix. */ + private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX; + + /** placeholder suffix. */ + private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX; + + /** + * {@link PlaceholderResolved} instance. + */ + private PlaceholderResolved resolvedInterceptor; + + /** all parsed placeholders will store here. */ + private Set visitedPlaceholders = new HashSet(50); + + /** + * Constructor method. + * + * @param resolvedInterceptor {@link PlaceholderResolved} can not be null. + */ + public PlaceholderResolver( + PlaceholderResolved resolvedInterceptor) { + if (resolvedInterceptor == null) { + throw new IllegalArgumentException( + "property 'resolvedInterceptor' is null"); + } + this.resolvedInterceptor = resolvedInterceptor; + } + + /** + * Do parser placeholder action. + * + * + * @param strVal target string to parser + * @return target string after placeholder parse + */ + public String doParse(String strVal) { + if (strVal == null) { + return strVal; + } + return parseStringValue(strVal, visitedPlaceholders); + } + + /** + * test if target string contains placeholderPrefix. + * + * @param strVal target string to test + * @return true if string contains placeholderPrefix + */ + public boolean hasPlaceHolder(String strVal) { + if (StringUtils.isBlank(strVal)) { + return false; + } + int startIndex = strVal.indexOf(this.placeholderPrefix); + if (startIndex == -1) { + return false; + } + return true; + } + + /** + * Parse the given String value recursively, to be able to resolve nested + * placeholders (when resolved property values in turn contain placeholders + * again). + * + * @param strVal the String value to parse + * @param visitedPlaceholders the placeholders that have already been visited + * during the current resolution attempt (used to detect circular references + * between placeholders). Only non-null if we're parsing a nested placeholder. + * @return the string + */ + protected String parseStringValue(String strVal, + Set visitedPlaceholders) { + + StringBuilder buf = new StringBuilder(strVal); + + int startIndex = strVal.indexOf(this.placeholderPrefix); + while (startIndex != -1) { + int endIndex = findPlaceholderEndIndex(buf, startIndex); + if (endIndex != -1) { + String placeholder = buf.substring(startIndex + + this.placeholderPrefix.length(), endIndex); + if (!visitedPlaceholders.add(placeholder)) { + throw new RuntimeException( + "Circular placeholder reference '" + placeholder + + "' in property definitions"); + } + // Recursive invocation, parsing placeholders contained in the + // placeholder key. + placeholder = parseStringValue(placeholder, visitedPlaceholders); + // Now obtain the value for the fully resolved key... + String propVal = resolvedInterceptor.doResolved(placeholder); + + if (propVal != null) { + // Recursive invocation, parsing placeholders contained in the + // previously resolved placeholder value. + propVal = parseStringValue(propVal, visitedPlaceholders); + buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); + + LOGGER.log(Level.FINEST, "Resolved placeholder '" + placeholder + "'"); + startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length()); + } + else { + startIndex = buf.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); + } + visitedPlaceholders.remove(placeholder); + } + else { + startIndex = -1; + } + } + + return buf.toString(); + } + + /** + * To find placeholder position from index. + * + * @param buf target string + * @param startIndex start index + * @return -1 if not found or return position index. + */ + private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { + int index = startIndex + this.placeholderPrefix.length(); + int withinNestedPlaceholder = 0; + while (index < buf.length()) { + if (substringMatch(buf, index, this.placeholderSuffix)) { + if (withinNestedPlaceholder > 0) { + withinNestedPlaceholder--; + index = index + this.placeholderSuffix.length(); + } + else { + return index; + } + } + else if (substringMatch(buf, index, this.placeholderPrefix)) { + withinNestedPlaceholder++; + index = index + this.placeholderPrefix.length(); + } + else { + index++; + } + } + return -1; + } + + /** + * Test whether the given string matches the given substring + * at the given index. + * + * @param str the original string (or StringBuffer) + * @param index the index in the original string to start matching against + * @param substring the substring to match at the given index + * @return true, if successful + */ + public static boolean substringMatch(CharSequence str, int index, CharSequence substring) { + for (int j = 0; j < substring.length(); j++) { + int i = index + j; + if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { + return false; + } + } + return true; + } + + /** + * Sets the placeholder prefix. + * + * @param placeholderPrefix the new placeholder prefix + */ + public void setPlaceholderPrefix(String placeholderPrefix) { + this.placeholderPrefix = placeholderPrefix; + } + + /** + * Sets the placeholder suffix. + * + * @param placeholderSuffix the new placeholder suffix + */ + public void setPlaceholderSuffix(String placeholderSuffix) { + this.placeholderSuffix = placeholderSuffix; + } + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/PropertyPlaceholderConfigurerTool.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/PropertyPlaceholderConfigurerTool.java new file mode 100644 index 00000000..816dcca4 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/PropertyPlaceholderConfigurerTool.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Properties; + +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.springframework.util.ReflectionUtils; + +/** + * Utility class for {@link PropertyPlaceholderConfigurer}. + * + * @author xiemalin + * @since 2.17 + */ +public final class PropertyPlaceholderConfigurerTool { + + /** + * get {@link Properties} instance from {@link ConfigurableListableBeanFactory}. + * + * @param beanFactory spring container + * @return {@link Properties} instance + */ + public static Properties getRegisteredPropertyResourceConfigurer( + ConfigurableListableBeanFactory beanFactory) { + Class clazz = PropertyPlaceholderConfigurer.class; + Map beans = beanFactory.getBeansOfType(clazz); + if (beans == null || beans.isEmpty()) { + return null; + } + + Object config = ((Map.Entry)beans.entrySet().iterator().next()).getValue(); + if (clazz.isAssignableFrom(config.getClass())) { + Method m = ReflectionUtils.findMethod(clazz, "mergeProperties", new Class[0]); + if (m != null) { + m.setAccessible(true); + return (Properties) ReflectionUtils.invokeMethod(m, config); + } + } + return null; + } + + /** + * To create placeholder parser. + * + * @param propertyResource {@link Properties} instance + * @return {@link PlaceholderResolver} instance + */ + public static PlaceholderResolver createPlaceholderParser( + final Properties propertyResource) { + if (propertyResource == null) { + return null; + } + PlaceholderResolver resolver = new PlaceholderResolver( + new PlaceholderResolved() { + public String doResolved(String placeholder) { + return propertyResource.getProperty(placeholder); + } + }); + return resolver; + } +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcProxyFactoryBean.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcProxyFactoryBean.java new file mode 100644 index 00000000..3bbffe3c --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcProxyFactoryBean.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import com.baidu.brpc.client.BrpcProxy; +import com.baidu.brpc.client.RpcClient; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.naming.NamingOptions; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +import java.util.List; + +/** + * {@link FactoryBean} for PbRpc proxies. + * + * @author xiemalin + * @since 2.0.2 + */ +@Setter +@Getter +public class RpcProxyFactoryBean extends RpcClientOptions + implements FactoryBean, InitializingBean, DisposableBean { + + /** The service interface. */ + private Class serviceInterface; + + /** naming service url */ + private String namingServiceUrl; + + /** + * identify different service implementation for the same interface. + */ + private String group = "normal"; + + /** + * identify service version. + */ + private String version = "1.0.0"; + + /** + * if true, naming service will throw exception when register/subscribe exceptions. + */ + private boolean ignoreFailOfNamingService = false; + + /** + * use serviceId to identify all instances for this service. + */ + private String serviceId; + + /** The interceptors. */ + private List interceptors; + + /** The service proxy. */ + private Object serviceProxy; + + /** The rpc client. */ + private RpcClient rpcClient; + + /** + * Sets the service interface. + * + * @param serviceInterface the new service interface + */ + public void setServiceInterface(Class serviceInterface) { + if (serviceInterface != null && !serviceInterface.isInterface()) { + throw new IllegalArgumentException("'serviceInterface' must be an interface"); + } + this.serviceInterface = serviceInterface; + } + + /** + * Gets the service interface. + * + * @return the service interface + */ + public Class getServiceInterface() { + return this.serviceInterface; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ + @Override + public Object getObject() throws Exception { + return serviceProxy; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + @Override + public Class getObjectType() { + return serviceInterface; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.FactoryBean#isSingleton() + */ + @Override + public boolean isSingleton() { + return true; + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + if (rpcClient == null) { + rpcClient = new RpcClient(namingServiceUrl, this, interceptors); + } + NamingOptions namingOptions = new NamingOptions(); + namingOptions.setGroup(group); + namingOptions.setVersion(version); + namingOptions.setIgnoreFailOfNamingService(ignoreFailOfNamingService); + namingOptions.setServiceId(serviceId); + this.serviceProxy = BrpcProxy.getProxy(rpcClient, serviceInterface, namingOptions); + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + @Override + public void destroy() throws Exception { + if (rpcClient != null) { + rpcClient.stop(); + } + } + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcServiceExporter.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcServiceExporter.java new file mode 100644 index 00000000..0ff9cbdd --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/RpcServiceExporter.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.server.RpcServer; +import com.baidu.brpc.server.RpcServerOptions; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * PBRPC exporter for standard PROTOBUF RPC implementation from jprotobuf-rpc-socket. + * + * @author xiemalin + * @since 2.17 + */ +@Setter +@Getter +@Slf4j +public class RpcServiceExporter extends RpcServerOptions implements InitializingBean, DisposableBean { + /** + * The pr rpc server. + */ + private RpcServer prRpcServer; + + /** + * The service port. + */ + private int servicePort; + + /** + * the register services which use default thread pool + */ + private List registerServices = new ArrayList(); + + /** + * the register services which use individual thread pool + */ + private Map customOptionsServiceMap = new HashMap(); + + /** + * {@link NamingOptions} for services + */ + private Map serviceNamingOptions = new HashMap(); + + /** + * The interceptor. + */ + private List interceptors = new ArrayList(); + + /* (non-Javadoc) + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + @Override + public void destroy() throws Exception { + if (prRpcServer != null) { + prRpcServer.shutdown(); + } + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.isTrue(servicePort > 0, "invalid service port: " + servicePort); + if (registerServices.size() == 0 && customOptionsServiceMap.size() == 0) { + throw new IllegalArgumentException("No register service specified."); + } + + prRpcServer = new RpcServer(servicePort, this, interceptors); + + for (Object service : registerServices) { + NamingOptions namingOptions = serviceNamingOptions.get(service); + prRpcServer.registerService(service, AopUtils.getTargetClass(service), namingOptions, null); + } + + for (Map.Entry entry : customOptionsServiceMap.entrySet()) { + NamingOptions namingOptions = serviceNamingOptions.get(entry.getValue()); + prRpcServer.registerService(entry.getValue(), AopUtils.getTargetClass(entry.getValue()), namingOptions, + entry.getKey()); + } + + prRpcServer.start(); + } + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AbstractAnnotationParserCallback.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AbstractAnnotationParserCallback.java new file mode 100644 index 00000000..5fc3039b --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AbstractAnnotationParserCallback.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import com.baidu.brpc.spring.PlaceholderResolver; +import org.apache.commons.lang3.StringUtils; + +/** + * Base annotation parser call back class. + * + * @author xiemalin + * @since 2.17 + */ +public abstract class AbstractAnnotationParserCallback implements + AnnotationParserCallback { + + + /** configuration resource placeholder resolver. */ + private PlaceholderResolver resolver; + + /** + * do parser action. + * + * @param value to parser + * @return value parser by {@link PlaceholderResolver} + */ + public String parsePlaceholder(String value) { + if (resolver != null) { + return resolver.doParse(value); + } + return value; + } + + /** + * test if value contains placeholder marked string. + * + * @param value to test + * @return true if string is null or contains placeholder marked string + */ + public boolean hasPlaceholder(String value) { + if (StringUtils.isBlank(value)) { + return false; + } + if (resolver != null) { + return resolver.hasPlaceHolder(value); + } + return false; + } + + /* (non-Javadoc) + * @see com.baidu.jprotobuf.pbrpc.spring.annotation.AnnotationParserCallback#setPlaceholderResolver(com.baidu.jprotobuf.pbrpc.spring.PlaceholderResolver) + */ + public void setPlaceholderResolver(PlaceholderResolver resolver) { + this.resolver = resolver; + } + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AnnotationParserCallback.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AnnotationParserCallback.java new file mode 100644 index 00000000..ccf46796 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/AnnotationParserCallback.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; + +import com.baidu.brpc.spring.PlaceholderResolver; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +/** + * Annotation parser call back interface. + * + * @author xiemalin + * @see org.springframework.context.annotation.CommonAnnotationBeanPostProcessor + */ +public interface AnnotationParserCallback { + + /** + * process all annotation on class type. + * + * @param t + * annotation instance. + * @param bean + * target bean + * @param beanName + * target bean name + * @param beanFactory + * spring bean factory + * @return wrapped bean + * @throws BeansException + * exceptions on spring beans create error. + */ + Object annotationAtType(Annotation t, Object bean, String beanName, + ConfigurableListableBeanFactory beanFactory) throws BeansException; + + /** + * process all annotation on class type after spring containter started. + * + * @param t annotation instance. + * @param bean target bean + * @param beanName target bean name + * @param beanFactory spring bean factory + * @throws BeansException exceptions on spring beans create error. + */ + void annotationAtTypeAfterStarted(Annotation t, Object bean, + String beanName, ConfigurableListableBeanFactory beanFactory) + throws BeansException; + + /** + * process all annotation on class field. + * + * @param t + * annotation instance. + * @param value + * field value of target target + * @param beanName + * target bean name + * @param pvs + * bean property values + * @param beanFactory + * spring bean factory + * @param field + * field instance + * @return field value + * @throws BeansException + * exceptions on spring beans create error. + */ + Object annotationAtField(Annotation t, Object value, String beanName, + PropertyValues pvs, DefaultListableBeanFactory beanFactory, + Field field) throws BeansException; + + /** + * process all annotation on class method. + * + * @param t + * annotation instance. + * @param bean + * target bean + * @param beanName + * target bean name + * @param pvs + * bean property values + * @param beanFactory + * spring bean factory + * @param method + * method instance + * @return method invoke parameter + * @throws BeansException + * exceptions on spring beans create error. + */ + Object annotationAtMethod(Annotation t, Object bean, String beanName, + PropertyValues pvs, DefaultListableBeanFactory beanFactory, + Method method) throws BeansException; + + /** + * Gets the type annotation. + * + * @return the type annotation + */ + Class getTypeAnnotation(); + + /** + * Gets the method field annotation. + * + * @return the method field annotation + */ + List> getMethodFieldAnnotation(); + + /** + * do destroy action on spring container close. + * + * @throws Exception + * throw any exception + */ + void destroy() throws Exception; + + /** + * Sets the placeholder resolver. + * + * @param resolver the new placeholder resolver + */ + void setPlaceholderResolver(PlaceholderResolver resolver); + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/CommonAnnotationBeanPostProcessor.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/CommonAnnotationBeanPostProcessor.java new file mode 100644 index 00000000..7e4ef93d --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/CommonAnnotationBeanPostProcessor.java @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; +import org.springframework.beans.factory.annotation.InjectionMetadata; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.ContextStartedEvent; +import org.springframework.core.GenericTypeResolver; +import org.springframework.core.MethodParameter; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +import com.baidu.brpc.spring.PlaceholderResolver; +import com.baidu.brpc.spring.PropertyPlaceholderConfigurerTool; + +/** + * Common annotation bean post processor. it uses {@link AnnotationParserCallback}
+ * interface to define specified {@link Annotation} then recognize the Class to do
+ * bean define action + * + * @author xiemalin + * @see AnnotationParserCallback + */ +public class CommonAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter + implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, DisposableBean, + InitializingBean, ApplicationListener { + + /** log this class. */ + protected static final Log LOGGER = LogFactory.getLog(AutowiredAnnotationBeanPostProcessor.class); + + /** call back class for {@link AnnotationParserCallback}. */ + private AnnotationParserCallback callback; + + /** + * start lowest order in spring container. + */ + private int order = Ordered.LOWEST_PRECEDENCE - 3; + + /** {@link ConfigurableListableBeanFactory} instance. */ + private DefaultListableBeanFactory beanFactory; + + /** all injected meta data. */ + private final Map, InjectionMetadata> injectionMetadataCache = + new ConcurrentHashMap, InjectionMetadata>(); + + /** loaded property instance. */ + private Properties propertyResource; + + /** to support placeholder. */ + private PlaceholderResolver resolver; + + /** + * management function to register all resolved bean has target annotation info. + */ + private Vector typeAnnotationedBeans = new Vector(); + + /** status to control start only once. */ + private AtomicBoolean started = new AtomicBoolean(false); + + /** + * Gets the call back class for {@link AnnotationParserCallback}. + * + * @return the call back class for {@link AnnotationParserCallback} + */ + private AnnotationParserCallback getCallback() { + return callback; + } + + /** + * Sets the call back class for {@link AnnotationParserCallback}. + * + * @param callback the new call back class for {@link AnnotationParserCallback} + */ + public void setCallback(AnnotationParserCallback callback) { + this.callback = callback; + } + + /** + * Sets the start lowest order in spring container. + * + * @param order the new start lowest order in spring container + */ + public void setOrder(int order) { + this.order = order; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.core.Ordered#getOrder() + */ + public int getOrder() { + return this.order; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) + */ + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { + throw new IllegalArgumentException( + "CommonAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory"); + } + this.beanFactory = (DefaultListableBeanFactory) beanFactory; + } + + /** + * To parse all initialized bean from spring which has target annotation matches. + * + * @param bean original bean initialize by spring + * @param beanName bean name defined in spring + * @return wrapped object by {@link AnnotationParserCallback} + * @throws BeansException in case of initialization errors + */ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (getCallback() == null) { + return super.postProcessBeforeInitialization(bean, beanName); + } + + Class clazz = bean.getClass(); + Class annotation; + annotation = getCallback().getTypeAnnotation(); + if (annotation == null) { + return bean; + } + Annotation a = clazz.getAnnotation(annotation); + if (a == null) { + return bean; + } + BeanInfo beanInfo = new BeanInfo(beanName, a); + typeAnnotationedBeans.add(beanInfo); + return getCallback().annotationAtType(a, bean, beanName, beanFactory); + } + + /** + * Post-process the given merged bean definition for the specified bean. + * + * @param beanDefinition the merged bean definition for the bean + * @param beanType the actual type of the managed bean instance + * @param beanName the name of the bean + */ + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + List> annotations = getCallback().getMethodFieldAnnotation(); + if (beanType != null && getCallback() != null && annotations != null) { + InjectionMetadata metadata = findAnnotationMetadata(beanType, annotations); + metadata.checkConfigMembers(beanDefinition); + } + } + + /** + * Post-process the given property values before the factory applies them to the given bean. Allows for checking + * whether all dependencies have been satisfied, for example based on a "Required" annotation on bean property + * setters. + *

+ * Also allows for replacing the property values to apply, typically through creating a new MutablePropertyValues + * instance based on the original PropertyValues, adding or removing specific values. + * + * @param pvs the property values that the factory is about to apply (never {@code null}) + * @param pds the relevant property descriptors for the target bean (with ignored dependency types - which the + * factory handles specifically - already filtered out) + * @param bean the bean instance created, but whose properties have not yet been set + * @param beanName the name of the bean + * @return the actual property values to apply to to the given bean (can be the passed-in PropertyValues instance), + * or {@code null} to skip property population + * @throws BeansException the beans exception + * @throws org.springframework.beans.BeansException in case of errors + * @see org.springframework.beans.MutablePropertyValues + */ + public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, + String beanName) throws BeansException { + List> annotations = getCallback().getMethodFieldAnnotation(); + if (getCallback() == null || annotations == null) { + return pvs; + } + + InjectionMetadata metadata = findAnnotationMetadata(bean.getClass(), annotations); + try { + metadata.inject(bean, beanName, pvs); + } catch (Throwable ex) { + throw new BeanCreationException(beanName, "Autowiring of methods failed", ex); + } + + return pvs; + } + + /** + * To resolve annotation meta data info from target class. + * + * @param clazz target class to resolve + * @param annotation marked annotation type + * @return all fields and methods matched target annotation type from specified class + */ + private InjectionMetadata findAnnotationMetadata(final Class clazz, + final List> annotation) { + // Quick check on the concurrent map first, with minimal locking. + InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); + if (metadata == null) { + synchronized (this.injectionMetadataCache) { + metadata = this.injectionMetadataCache.get(clazz); + if (metadata == null) { + LinkedList elements; + elements = new LinkedList(); + parseFields(clazz, annotation, elements); + parseMethods(clazz, annotation, elements); + + metadata = new InjectionMetadata(clazz, elements); + this.injectionMetadataCache.put(clazz, metadata); + } + } + } + return metadata; + } + + /** + * To parse all method to find out annotation info. + * + * @param clazz target class + * @param annotions the annotions + * @param elements injected element of all methods + */ + protected void parseMethods(final Class clazz, final List> annotions, + final LinkedList elements) { + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + for (Class anno : annotions) { + Annotation annotation = method.getAnnotation(anno); + if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Autowired annotation is not supported on static methods"); + } + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException( + "Autowired annotation requires at least one argument: " + method); + } + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + elements.add(new AutowiredMethodElement(method, annotation, pd)); + } + } + } + }); + } + + /** + * To parse all field to find out annotation info. + * + * @param clazz target class + * @param annotations the annotations + * @param elements injected element of all fields + */ + protected void parseFields(final Class clazz, final List> annotations, + final LinkedList elements) { + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + for (Class anno : annotations) { + Annotation annotation = field.getAnnotation(anno); + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Autowired annotation is not supported on static fields"); + } + elements.add(new AutowiredFieldElement(field, annotation)); + } + } + } + }); + } + + /** + * Class representing injection information about an annotated field. + */ + private class AutowiredFieldElement extends InjectionMetadata.InjectedElement { + + /** target annotation type. */ + private final Annotation annotation; + + /** + * Constructor with field and annotation type. + * + * @param field field instance + * @param annotation annotation type + */ + public AutowiredFieldElement(Field field, Annotation annotation) { + super(field, null); + this.annotation = annotation; + } + + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + Field field = (Field) this.member; + try { + ReflectionUtils.makeAccessible(field); + Object value = field.get(bean); + value = getCallback().annotationAtField(annotation, value, beanName, pvs, beanFactory, field); + if (value != null) { + ReflectionUtils.makeAccessible(field); + field.set(bean, value); + } + } catch (Throwable ex) { + throw new BeanCreationException("Could not autowire field: " + field, ex); + } + } + } + + /** + * Class representing injection information about an annotated method. + */ + private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { + + /** target annotation type. */ + private final Annotation annotation; + + /** + * Constructor with method and annotation type. + * + * @param method method instance + * @param annotation annotation type + * @param pd {@link PropertyDescriptor} instance. + */ + public AutowiredMethodElement(Method method, Annotation annotation, PropertyDescriptor pd) { + super(method, pd); + this.annotation = annotation; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject(java.lang.Object, + * java.lang.String, org.springframework.beans.PropertyValues) + */ + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + if (this.skip == null && this.pd != null && pvs != null && pvs.contains(this.pd.getName())) { + // Explicit value provided as part of the bean definition. + this.skip = Boolean.TRUE; + } + if (this.skip != null && this.skip.booleanValue()) { + return; + } + Method method = (Method) this.member; + try { + Object[] arguments = null; + + Class[] paramTypes = method.getParameterTypes(); + arguments = new Object[paramTypes.length]; + + for (int i = 0; i < arguments.length; i++) { + MethodParameter methodParam = new MethodParameter(method, i); + GenericTypeResolver.resolveParameterType(methodParam, bean.getClass()); + arguments[i] = + getCallback().annotationAtMethod(annotation, bean, beanName, pvs, beanFactory, method); + + if (arguments[i] == null) { + arguments = null; + break; + } + } + + if (this.skip == null) { + if (this.pd != null && pvs instanceof MutablePropertyValues) { + ((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName()); + } + this.skip = Boolean.FALSE; + } + if (arguments != null) { + ReflectionUtils.makeAccessible(method); + method.invoke(bean, arguments); + } + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } catch (Throwable ex) { + throw new BeanCreationException("Could not autowire method: " + method, ex); + } + } + } + + /** + * Invoke callback destroy method. + * + * @throws Exception in case of callback do destroy action error + */ + public void destroy() throws Exception { + if (getCallback() != null) { + getCallback().destroy(); + } + + } + + /** + * Initialize propertyResource instance load. + * + * @throws Exception in case of any error + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(getCallback(), "property 'callback' must be set"); + + propertyResource = PropertyPlaceholderConfigurerTool + .getRegisteredPropertyResourceConfigurer((ConfigurableListableBeanFactory) beanFactory); + if (resolver == null) { + resolver = PropertyPlaceholderConfigurerTool.createPlaceholderParser(propertyResource); + } + + if (getCallback() != null) { + getCallback().setPlaceholderResolver(resolver); + } + + } + + /** + * Do annotation on class type resolve action after spring container started. + * + * @param event spring application event + */ + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ContextStartedEvent || event instanceof ContextRefreshedEvent) { + + // only execute this method once. bug fix for ContextRefreshedEvent will invoke twice on spring MVC servlet + if (started.compareAndSet(false, true)) { + for (BeanInfo bean : typeAnnotationedBeans) { + if (getCallback() != null) { + Object targetBean = beanFactory.getBean(bean.name); + getCallback().annotationAtTypeAfterStarted(bean.annotation, targetBean, bean.name, beanFactory); + } + } + } else { + LOGGER.warn("onApplicationEvent of application event [" + event + + "] ignored due to processor already started."); + } + + } + + } + + /** + * Wrapped bean info. + * + * @author xiemalin + * @since 1.0.0.0 + */ + private static class BeanInfo { + + /** bean name. */ + private String name; + + /** annotation type. */ + private Annotation annotation; + + /** + * Constructor with bean, name and annotation type. + * + * @param name bean name + * @param annotation annotation type + */ + public BeanInfo(String name, Annotation annotation) { + super(); + this.name = name; + this.annotation = annotation; + } + + } + +} \ No newline at end of file diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/NamingOption.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/NamingOption.java new file mode 100644 index 00000000..8b55ba2b --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/NamingOption.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring.annotation; + + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Extra options for {@link com.baidu.brpc.naming.NamingService} + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface NamingOption { + /** + * Key of the option + */ + String key() default ""; + + /** + * Value of the option + */ + String value() default ""; +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolver.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolver.java new file mode 100644 index 00000000..a725a4b2 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolver.java @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; + +import com.baidu.bjf.remoting.protobuf.utils.JDKCompilerHelper; +import com.baidu.bjf.remoting.protobuf.utils.compiler.Compiler; +import com.baidu.brpc.client.RpcClientOptions; +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.naming.NamingOptions; +import com.baidu.brpc.naming.NamingServiceFactory; +import com.baidu.brpc.server.RpcServerOptions; +import com.baidu.brpc.spring.RpcProxyFactoryBean; +import com.baidu.brpc.spring.RpcServiceExporter; + +import lombok.Getter; +import lombok.Setter; + +/** + * Supports annotation resolver for {@link RpcProxy} and {@link RpcExporter}. + * + * @author xiemalin + * @since 2.0.0 + */ +@Setter +@Getter +public class RpcAnnotationResolver extends AbstractAnnotationParserCallback implements InitializingBean { + + /** + * log this class. + */ + protected static final Log LOGGER = LogFactory.getLog(RpcAnnotationResolver.class); + + /** + * The rpc clients. + */ + private List rpcClients = new ArrayList(); + + /** + * The port mapping exporters. + */ + private Map portMappingExporters = new HashMap(); + + /** + * The compiler. + */ + private Compiler compiler; + + /** + * status to control start only once. + */ + private AtomicBoolean started = new AtomicBoolean(false); + + /* the default naming service url */ + private String namingServiceUrl; + + /** + * The default registry center service for all service + */ + private NamingServiceFactory namingServiceFactory; + + /** + * The default interceptors for all service + */ + private List interceptors = new ArrayList(); + + /** + * The protobuf rpc annotation resolver listener. + */ + private RpcAnnotationResolverListener protobufRpcAnnotationResolverListener; + + @Override + public Object annotationAtType(Annotation t, Object bean, String beanName, + ConfigurableListableBeanFactory beanFactory) throws BeansException { + if (t instanceof RpcExporter) { + LOGGER.info("Annotation 'RpcExporter' for target '" + beanName + "' created"); + + // to fix AOP effective of target bean so instead of using + // beanFactory.getBean(beanName) + parseRpcExporterAnnotation((RpcExporter) t, beanFactory, beanFactory.getBean(beanName)); + } + return bean; + } + + /** + * Parses the rpc exporter annotation. + * + * @param rpcExporter the rpc exporter + * @param beanFactory the bean factory + * @param bean the bean + */ + private void parseRpcExporterAnnotation(RpcExporter rpcExporter, ConfigurableListableBeanFactory beanFactory, + Object bean) { + + String port = parsePlaceholder(rpcExporter.port()); + // convert to integer and throw exception on error + int intPort = Integer.parseInt(port); + + // if there are multi service on one port, the first service configs effect only. + RpcServiceExporter rpcServiceExporter = portMappingExporters.get(intPort); + if (rpcServiceExporter == null) { + rpcServiceExporter = new RpcServiceExporter(); + rpcServiceExporter.setServicePort(intPort); + portMappingExporters.put(intPort, rpcServiceExporter); + } + + // get RpcServerOptions + String rpcServerOptionsBeanName = parsePlaceholder(rpcExporter.rpcServerOptionsBeanName()); + RpcServerOptions rpcServerOptions; + if (StringUtils.isBlank(rpcServerOptionsBeanName)) { + rpcServerOptions = new RpcServerOptions(); + } else { + // if not exist throw exception + rpcServerOptions = beanFactory.getBean(rpcServerOptionsBeanName, RpcServerOptions.class); + } + // naming service url + if (StringUtils.isBlank(rpcServerOptions.getNamingServiceUrl())) { + rpcServerOptions.setNamingServiceUrl(namingServiceUrl); + rpcServiceExporter.setNamingServiceUrl(namingServiceUrl); + } + + if (rpcExporter.useServiceSharedThreadPool()) { + try { + rpcServiceExporter.copyFrom(rpcServerOptions); + } catch (Exception ex) { + throw new RuntimeException("copy server options failed:", ex); + } + } + + // interceptor + String interceptorNames = parsePlaceholder(rpcExporter.interceptorBeanNames()); + if (!StringUtils.isBlank(interceptorNames)) { + List customInterceptors = new ArrayList(); + String[] interceptorNameArray = interceptorNames.split(","); + for (String interceptorName : interceptorNameArray) { + Interceptor interceptor = beanFactory.getBean(interceptorName, Interceptor.class); + customInterceptors.add(interceptor); + } + rpcServiceExporter.setInterceptors(customInterceptors); + } else { + rpcServiceExporter.setInterceptors(interceptors); + } + + // naming options + NamingOptions namingOptions = new NamingOptions(); + // Populate NamingOptions from the annotation + if (!rpcExporter.group().isEmpty()) { + namingOptions.setGroup(parsePlaceholder(rpcExporter.group())); + } + if (!rpcExporter.version().isEmpty()) { + namingOptions.setVersion(parsePlaceholder(rpcExporter.version())); + } + if (rpcExporter.extraOptions().length > 0) { + namingOptions.setExtra(new HashMap()); + for (int i = 0; i < rpcExporter.extraOptions().length; i++) { + NamingOption opt = rpcExporter.extraOptions()[i]; + namingOptions.getExtra().put(opt.key(), parsePlaceholder(opt.value())); + } + } + namingOptions.setIgnoreFailOfNamingService(rpcExporter.ignoreFailOfNamingService()); + rpcServiceExporter.getServiceNamingOptions().put(bean, namingOptions); + + // do register service + if (rpcExporter.useServiceSharedThreadPool()) { + rpcServiceExporter.getRegisterServices().add(bean); + } else { + rpcServiceExporter.getCustomOptionsServiceMap().put(rpcServerOptions, bean); + } + + if (protobufRpcAnnotationResolverListener != null) { + protobufRpcAnnotationResolverListener.onRpcExporterAnnotationParsered( + rpcExporter, intPort, bean, rpcServiceExporter.getRegisterServices()); + } + } + + @Override + public void annotationAtTypeAfterStarted(Annotation t, Object bean, String beanName, + ConfigurableListableBeanFactory beanFactory) throws BeansException { + + if (started.compareAndSet(false, true)) { + // do export service here + Collection values = portMappingExporters.values(); + for (RpcServiceExporter rpcServiceExporter : values) { + try { + rpcServiceExporter.afterPropertiesSet(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + } + + /* + * (non-Javadoc) + * + * @see com.baidu.brpc.spring.annotation.AnnotationParserCallback# + * annotationAtField(java.lang.annotation. Annotation, java.lang.Object, java.lang.String, + * org.springframework.beans.PropertyValues, + * org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.lang.reflect.Field) + */ + @Override + public Object annotationAtField(Annotation t, Object value, String beanName, PropertyValues pvs, + DefaultListableBeanFactory beanFactory, Field field) throws BeansException { + if (t instanceof RpcProxy) { + try { + LOGGER.info("Annotation 'BrpcProxy' on field '" + field.getName() + "' for target '" + beanName + + "' created"); + return parseRpcProxyAnnotation((RpcProxy) t, field.getType(), beanFactory); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + return value; + } + + /** + * Parses the rpc proxy annotation. + * + * @param rpcProxy the rpc proxy + * @param beanFactory the bean factory + * @return the object + * @throws Exception the exception + */ + private Object parseRpcProxyAnnotation(RpcProxy rpcProxy, + Class serviceInterface, + DefaultListableBeanFactory beanFactory) + throws Exception { + RpcProxyFactoryBean rpcProxyFactoryBean; + String factoryBeanName = "&" + serviceInterface.getSimpleName(); + try { + rpcProxyFactoryBean = beanFactory.getBean(factoryBeanName, RpcProxyFactoryBean.class); + if (rpcProxyFactoryBean != null) { + return rpcProxyFactoryBean.getObject(); + } + } catch (NoSuchBeanDefinitionException ex) { + // continue the following logic to create new factory bean + } + + // get RpcClientOptions + String rpcClientOptionsBeanName = parsePlaceholder(rpcProxy.rpcClientOptionsBeanName()); + RpcClientOptions rpcClientOptions; + if (StringUtils.isBlank(rpcClientOptionsBeanName)) { + rpcClientOptions = new RpcClientOptions(); + } else { + // if not exist throw exception + rpcClientOptions = beanFactory.getBean(rpcClientOptionsBeanName, RpcClientOptions.class); + } + + // naming service url + String actualNamingServiceUrl; + if (StringUtils.isNotBlank(rpcProxy.namingServiceUrl())) { + actualNamingServiceUrl = parsePlaceholder(rpcProxy.namingServiceUrl()); + } else { + actualNamingServiceUrl = namingServiceUrl; + } + + rpcProxyFactoryBean = createRpcProxyFactoryBean(rpcProxy, serviceInterface, + beanFactory, rpcClientOptions, actualNamingServiceUrl); + + rpcClients.add(rpcProxyFactoryBean); + Object object = rpcProxyFactoryBean.getObject(); + if (protobufRpcAnnotationResolverListener != null) { + // TODO: why create new RpcProxyFactoryBean? +// RpcProxyFactoryBean newRpcProxyFactoryBean = +// createRpcProxyFactoryBean(rpcProxy, beanFactory, rpcClientOptions, serviceUrl); + protobufRpcAnnotationResolverListener.onRpcProxyAnnotationParsed(rpcProxy, rpcProxyFactoryBean, + rpcProxyFactoryBean.getObject()); + } + + return object; + } + + /** + * Creates the rpc proxy factory bean. + * + * @param rpcProxy the rpc proxy + * @param beanFactory the bean factory + * @param rpcClientOptions the rpc client options + * @param namingServiceUrl naming service url + * @return the rpc proxy factory bean + */ + protected RpcProxyFactoryBean createRpcProxyFactoryBean(RpcProxy rpcProxy, + Class serviceInterface, + DefaultListableBeanFactory beanFactory, + RpcClientOptions rpcClientOptions, + String namingServiceUrl) { + GenericBeanDefinition beanDef = new GenericBeanDefinition(); + beanDef.setBeanClass(RpcProxyFactoryBean.class); + MutablePropertyValues values = new MutablePropertyValues(); + for (Field field : rpcClientOptions.getClass().getDeclaredFields()) { + try { + field.setAccessible(true); + values.addPropertyValue(field.getName(), field.get(rpcClientOptions)); + } catch (Exception ex) { + LOGGER.warn("field not exist:", ex); + } + } + values.addPropertyValue("serviceInterface", serviceInterface); + values.addPropertyValue("namingServiceUrl", namingServiceUrl); + values.addPropertyValue("group", rpcProxy.group()); + values.addPropertyValue("version", rpcProxy.version()); + values.addPropertyValue("ignoreFailOfNamingService", rpcProxy.ignoreFailOfNamingService()); + values.addPropertyValue("serviceId", rpcProxy.name()); + + // interceptor + String interceptorNames = parsePlaceholder(rpcProxy.interceptorBeanNames()); + if (!StringUtils.isBlank(interceptorNames)) { + List customInterceptors = new ArrayList(); + String[] interceptorNameArray = interceptorNames.split(","); + for (String interceptorName : interceptorNameArray) { + Interceptor interceptor = beanFactory.getBean(interceptorName, Interceptor.class); + customInterceptors.add(interceptor); + } + values.addPropertyValue("interceptors", customInterceptors); + } else { + values.addPropertyValue("interceptors", interceptors); + } + + beanDef.setPropertyValues(values); + String serviceInterfaceBeanName = serviceInterface.getSimpleName(); + beanFactory.registerBeanDefinition(serviceInterfaceBeanName, beanDef); + return beanFactory.getBean("&" + serviceInterfaceBeanName, RpcProxyFactoryBean.class); + } + + /* + * (non-Javadoc) + * + * @see com.baidu.jprotobuf.pbrpc.spring.annotation.AnnotationParserCallback# + * annotationAtMethod(java.lang.annotation. Annotation, java.lang.Object, java.lang.String, + * org.springframework.beans.PropertyValues, + * org.springframework.beans.factory.config.DefaultListableBeanFactory, java.lang.reflect.Method) + */ + @Override + public Object annotationAtMethod(Annotation t, Object bean, String beanName, PropertyValues pvs, + DefaultListableBeanFactory beanFactory, Method method) throws BeansException { + if (t instanceof RpcProxy) { + try { + LOGGER.info("Annotation 'BrpcProxy' on method '" + method.getName() + "' for target '" + beanName + + "' created"); + return parseRpcProxyAnnotation((RpcProxy) t, method.getParameterTypes()[0], beanFactory); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + return null; + } + + /* + * (non-Javadoc) + * + * @see com.baidu.brpc.spring.annotation.AnnotationParserCallback# getTypeAnnotation() + */ + @Override + public Class getTypeAnnotation() { + return RpcExporter.class; + } + + /* + * (non-Javadoc) + * + * @see com.baidu.brpc.spring.annotation.AnnotationParserCallback# getMethodFieldAnnotation() + */ + @Override + public List> getMethodFieldAnnotation() { + List> list = new ArrayList>(); + list.add(RpcProxy.class); + return list; + } + + /* + * @see com.baidu.brpc.spring.annotation.AnnotationParserCallback + */ + @Override + public void destroy() throws Exception { + if (rpcClients != null) { + for (RpcProxyFactoryBean bean : rpcClients) { + try { + bean.destroy(); + } catch (Exception e) { + LOGGER.fatal(e.getMessage(), e.getCause()); + } + } + } + + if (portMappingExporters != null) { + Collection exporters = portMappingExporters.values(); + for (RpcServiceExporter rpcServiceExporter : exporters) { + try { + rpcServiceExporter.destroy(); + } catch (Exception e) { + LOGGER.fatal(e.getMessage(), e.getCause()); + } + } + } + + if (protobufRpcAnnotationResolverListener != null) { + protobufRpcAnnotationResolverListener.destroy(); + } + + } + + /** + * Sets the compiler. + * + * @param compiler the new compiler + */ + public void setCompiler(Compiler compiler) { + this.compiler = compiler; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + if (compiler != null) { + JDKCompilerHelper.setCompiler(compiler); + } + + } + +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolverListener.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolverListener.java new file mode 100644 index 00000000..6f5ebbbe --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcAnnotationResolverListener.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.util.List; + +import com.baidu.brpc.spring.RpcProxyFactoryBean; + +/** + * Listener class for {@link RpcAnnotationResolver} while doing annotation parser action. + * + * @author xiemalin + * @since 3.4.1 + */ +public interface RpcAnnotationResolverListener { + + /** + * This method will called after {@link RpcExporter} annotation parsed. + * + * @param rpcExporter {@link RpcExporter} annotation + * @param port real port + * @param bean target bean + * @param registerServices registered service list + */ + void onRpcExporterAnnotationParsered(RpcExporter rpcExporter, int port, Object bean, List registerServices); + + + /** + * Destroy. + */ + void destroy(); + + + /** + * This method will called after {@link RpcProxy} annotation parsed. + * + * @param rpcProxy {@link RpcProxy} annotation + * @param newRpcProxyFactoryBean a new created {@link RpcProxyFactoryBean} + * @param object target PROXY bean for this {@link RpcProxy} annotation delegated + */ + void onRpcProxyAnnotationParsed(RpcProxy rpcProxy, RpcProxyFactoryBean newRpcProxyFactoryBean, Object object); + + + +} + diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcExporter.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcExporter.java new file mode 100644 index 00000000..f5f79a7b --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcExporter.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.baidu.brpc.spring.RpcServiceExporter; + +/** + * Annotation publish for {@link RpcServiceExporter}. + * + * @author xiemalin + * @since 2.0.2 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface RpcExporter { + + /** + * RPC server port to publish. + * + * @return the string + */ + String port() default "8080"; + + /** + * bean name of RPC server options bean type must be {@link com.baidu.brpc.server.RpcServerOptions}. + * + * @return the string + */ + String rpcServerOptionsBeanName() default ""; + + /** + * bean name of RPC interceptor bean type must be {@link com.baidu.brpc.interceptor.Interceptor}. + * + * @return the string + */ + String interceptorBeanNames() default ""; + + /** + * Group for naming service + */ + String group() default "normal"; + + /** + * Version for naming service + */ + String version() default "1.0.0"; + + /** + * ignore it when failed to register naming service + * + * @return true, ignore + */ + boolean ignoreFailOfNamingService() default false; + + /** + * true: use the shared thread pool + * false: create individual thread pool for register service + * attention here - it is not global share thread pool between multi RpcClient/RpcServer , if you want to use + * global thread pool , see rpc options. + */ + boolean useServiceSharedThreadPool() default true; + + /** + * Extra naming options. This option is effective on service-scope. + *

+ * This config may have different behavior depending on which NamingService is used, + * consult documentation of the specific {@link com.baidu.brpc.naming.NamingService} for detailed usage. + */ + NamingOption[] extraOptions() default {}; +} diff --git a/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcProxy.java b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcProxy.java new file mode 100644 index 00000000..06564e76 --- /dev/null +++ b/brpc-spring/src/main/java/com/baidu/brpc/spring/annotation/RpcProxy.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation publish for {@link com.baidu.brpc.spring.RpcProxyFactoryBean}. + * + * @author xiemalin + * @since 2.17 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface RpcProxy { + + /** + * bean name of RPC client options. bean type must be {@link com.baidu.brpc.client.RpcClientOptions} + * + * @return the string + */ + String rpcClientOptionsBeanName() default ""; + + /** + * RPC server naming url to connect. + * + * @return the string + */ + String namingServiceUrl() default ""; + + /** + * group for naming service + * + */ + String group() default "normal"; + + /** + * version for naming service + * + */ + String version() default "1.0.0"; + + /** + * ignore it when failed to lookup/subscribe naming service + * + * @return true, ignore + */ + boolean ignoreFailOfNamingService() default false; + + /** + * bean name of RPC interceptor bean type must be {@link com.baidu.brpc.interceptor.Interceptor}. + * + * @return the string + */ + String interceptorBeanNames() default ""; + + /** + * use name to identify all the instances for this service from registry. + */ + String name() default ""; +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationEchoServiceClient.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationEchoServiceClient.java new file mode 100644 index 00000000..dce97cf7 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationEchoServiceClient.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.stereotype.Service; + +import com.baidu.brpc.spring.annotation.RpcProxy; + +/** + * Test class for {@link RpcProxy} + * + * @author xiemalin + * @since 2.17 + */ +@Service("echoServiceClient") +@Getter +@Setter +public class AnnotationEchoServiceClient { + + @RpcProxy(namingServiceUrl = "list://127.0.0.1:8012", + rpcClientOptionsBeanName = "rpcClientOptions", + interceptorBeanNames = "customInterceptor") + private EchoService echoService; +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.java new file mode 100644 index 00000000..d0334ec0 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + * + * @author xiemalin + * @since 2.17 + */ +public class AnnotationRpcXmlConfigurationTest extends RpcXmlConfigurationTestBase { + + protected String getConfigurationPath() { + return "classpath:" + AnnotationRpcXmlConfigurationTest.class.getName().replace('.', '/') + ".xml"; + } + + @Test + public void testCommonRpcRequest() { + + AnnotationEchoServiceClient annotationEchoServiceClient = + (AnnotationEchoServiceClient) context.getBean("echoServiceClient", AnnotationEchoServiceClient.class); + + // test common client + super.internalRpcRequestAndResponse(annotationEchoServiceClient.getEchoService()); + + } + + @Test + public void testHaRpcRequest() { + + AnnotationEchoServiceClient annotationEchoServiceClient = + (AnnotationEchoServiceClient) context.getBean("echoServiceClient", AnnotationEchoServiceClient.class); + + // test ha client + super.internalRpcRequestAndResponse(annotationEchoServiceClient.getEchoService()); + + } + + @Test + public void testHaRpcRequestWithPartialFailed() { + + AnnotationEchoServiceClient annotationEchoServiceClient = + (AnnotationEchoServiceClient) context.getBean("echoServiceClient", AnnotationEchoServiceClient.class); + + // test ha client + super.internalRpcRequestAndResponse(annotationEchoServiceClient.getEchoService()); + } + + protected void internalRpcRequestAndResponseTimeout(EchoService echoService) { + EchoRequest echo = new EchoRequest(); + echo.setMessage("world"); + + EchoResponse response = echoService.echo(echo); + Assert.assertEquals("world", response.getMessage()); + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/CustomInterceptor.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/CustomInterceptor.java new file mode 100644 index 00000000..9c79b2dd --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/CustomInterceptor.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring; + +import com.baidu.brpc.interceptor.AbstractInterceptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baidu.brpc.interceptor.Interceptor; +import com.baidu.brpc.protocol.Request; +import com.baidu.brpc.protocol.Response; + +public class CustomInterceptor extends AbstractInterceptor { + private static final Logger LOG = LoggerFactory.getLogger(CustomInterceptor.class); + + public boolean handleRequest(Request rpcRequest) { + LOG.info("request intercepted, logId={}, service={}, method={}", + rpcRequest.getLogId(), + rpcRequest.getTarget().getClass().getSimpleName(), + rpcRequest.getTargetMethod().getName()); + return true; + } + + public void handleResponse(Response response) { + if (response != null) { + LOG.info("reponse intercepted, logId={}, result={}", + response.getLogId(), response.getResult()); + } + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoRequest.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoRequest.java new file mode 100644 index 00000000..219e60e2 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoRequest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoRequest { + private String message; +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoResponse.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoResponse.java new file mode 100644 index 00000000..3f356884 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring; + +import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass; +import lombok.Getter; +import lombok.Setter; + +@ProtobufClass +@Setter +@Getter +public class EchoResponse { + private String message; +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoService.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoService.java new file mode 100644 index 00000000..c8bab40e --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring; + +import com.baidu.brpc.protocol.BrpcMeta; + +/** + * Created by huwenwei on 2018/11/23. + */ +public interface EchoService { + /** + * brpc/sofa: + * serviceName默认是包名 + 类名,methodName是proto文件Service内对应方法名, + * hulu: + * serviceName默认是类名,methodName是proto文件Service内对应方法index。 + */ + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") +// @BrpcMeta(serviceName = "EchoService", methodName = "0") + EchoResponse echo(EchoRequest request); +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoServiceImpl.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoServiceImpl.java new file mode 100644 index 00000000..31998394 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/EchoServiceImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring; + +import com.baidu.brpc.spring.annotation.RpcExporter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service("echoServiceImpl") +@RpcExporter(port = "8012", + rpcServerOptionsBeanName = "rpcServerOptions", + interceptorBeanNames = "customInterceptor") +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public EchoResponse echo(EchoRequest request) { + // 读取request attachment +// RpcContext rpcContext = RpcContext.getContext(); +// ByteBuf attachment = rpcContext.getRequestBinaryAttachment(); +// if (attachment != null) { +// if (LOG.isDebugEnabled()) { +// String attachmentString = new String(attachment.array()); +// LOG.debug("request attachment={}", attachmentString); +// } +// // 设置response attachment +// rpcContext.setResponseBinaryAttachment(Unpooled.copiedBuffer(attachment)); +// } + + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.java new file mode 100644 index 00000000..43f4206a --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Test class for {@link RpcServiceExporter} and {@link RpcProxyFactoryBean} by XML configuration. + * + * @author xiemalin + * @since 2.17 + */ + +public class HaRpcXmlConfigurationTest extends RpcXmlConfigurationTestBase { + + private RpcServiceExporter rpcServiceExporter1; + private RpcServiceExporter rpcServiceExporter2; + private RpcServiceExporter rpcServiceExporter3; + + /* + * (non-Javadoc) + * + * @see com.baidu.jprotobuf.pbrpc.spring.RpcXmlConfigurationTestBase#getConfigurationPath() + */ + @Override + protected String getConfigurationPath() { + return "classpath:" + HaRpcXmlConfigurationTest.class.getName().replace('.', '/') + ".xml"; + } + + @Before + public void setUp() { + super.setUp(); + rpcServiceExporter1 = (RpcServiceExporter) context.getBean("rpcServer1", RpcServiceExporter.class); + rpcServiceExporter2 = (RpcServiceExporter) context.getBean("rpcServer2", RpcServiceExporter.class); + rpcServiceExporter3 = (RpcServiceExporter) context.getBean("rpcServer3", RpcServiceExporter.class); + } + + @Test + public void testPartialServerFailed() throws Exception { + + EchoService echoService = (EchoService) context.getBean("echoServiceProxy"); + + // shutdown server1 + if (rpcServiceExporter1 != null) { + rpcServiceExporter1.destroy(); + } + + super.internalRpcRequestAndResponse(echoService); + + // shutdown server2 + if (rpcServiceExporter2 != null) { + rpcServiceExporter2.destroy(); + } + super.internalRpcRequestAndResponse(echoService); + + // shutdown all servers + if (rpcServiceExporter3 != null) { + rpcServiceExporter3.destroy(); + } + + Thread.sleep(5000); + + try { + super.internalRpcRequestAndResponse(echoService); + // should throw exception on no servers available + Assert.fail("No servers available should throw exception"); + } catch (Exception e) { + Assert.assertNotNull(e); + } + + // recover server1 + if (rpcServiceExporter1 != null) { + rpcServiceExporter1.afterPropertiesSet(); + } + + Thread.sleep(5000); + // server1 recover should test ok + super.internalRpcRequestAndResponse(echoService); + + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcProxyTest.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcProxyTest.java new file mode 100644 index 00000000..0acfd2f4 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcProxyTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * + * Test for {@link RpcProxyFactoryBean} and {@link RpcServiceExporter} + * + * @author xiemalin + * @since 2.1.0.0 + */ + +public class RpcProxyTest { + + private int servicePort = 1031; + + private RpcProxyFactoryBean rpcProxyFactoryBean; + + private RpcServiceExporter rpcServiceExporter; + + @Before + public void setUp() throws Exception { + + rpcServiceExporter = new RpcServiceExporter(); + rpcServiceExporter.setServicePort(servicePort); + + EchoServiceImpl service = new EchoServiceImpl(); + rpcServiceExporter.setRegisterServices(new ArrayList(Arrays.asList(service))); + + rpcServiceExporter.afterPropertiesSet(); + + // setup client + rpcProxyFactoryBean = new RpcProxyFactoryBean(); + rpcProxyFactoryBean.setServiceInterface(EchoService.class); + rpcProxyFactoryBean.setNamingServiceUrl("list://127.0.0.1:" + servicePort); + rpcProxyFactoryBean.afterPropertiesSet(); + + } + + @After + public void tearDown() { + if (rpcServiceExporter != null) { + try { + rpcServiceExporter.destroy(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void testClientSend() throws Exception { + Object object = rpcProxyFactoryBean.getObject(); + Assert.assertTrue(object instanceof EchoService); + + EchoService echoService = (EchoService) object; + + EchoRequest echo = new EchoRequest(); + echo.setMessage("world"); + + EchoResponse response = echoService.echo(echo); + Assert.assertEquals("world", response.getMessage()); + + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTest.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTest.java new file mode 100644 index 00000000..6e3bd398 --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import org.junit.Test; + + +/** + * Test class for {@link RpcServiceExporter} and {@link RpcProxyFactoryBean} by XML configuration. + * + * @author xiemalin + * @since 2.17 + */ + +public class RpcXmlConfigurationTest extends RpcXmlConfigurationTestBase { + + + /* + * (non-Javadoc) + * + * @see com.baidu.jprotobuf.pbrpc.spring.RpcXmlConfigurationTestBase#getConfigurationPath() + */ + @Override + protected String getConfigurationPath() { + return "classpath:" + RpcXmlConfigurationTest.class.getName().replace('.', '/') + ".xml"; + } + + + @Test + public void testRpcRequestAndResponse() { + EchoService echoService = context.getBean("echoServiceProxy", EchoService.class); + super.internalRpcRequestAndResponse(echoService); + } +} diff --git a/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTestBase.java b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTestBase.java new file mode 100644 index 00000000..88ad1c0f --- /dev/null +++ b/brpc-spring/src/test/java/com/baidu/brpc/spring/RpcXmlConfigurationTestBase.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * Base RPC XML configuration test class. + * + * @author xiemalin + * @since 2.17 + */ +public abstract class RpcXmlConfigurationTestBase { + + /** + * context of {@link AbstractApplicationContext} + */ + protected AbstractApplicationContext context; + + + + @Before + public void setUp() { + context = + new ClassPathXmlApplicationContext(getConfigurationPath()); + } + + protected abstract String getConfigurationPath(); + + @After + public void tearDown() { + if (context != null) { + context.close(); + } + } + + protected void internalRpcRequestAndResponse(EchoService echoService) { + EchoRequest echo = new EchoRequest(); + echo.setMessage("world"); + + EchoResponse response = echoService.echo(echo); + Assert.assertEquals("world", response.getMessage()); + } +} diff --git a/brpc-spring/src/test/resources/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.xml b/brpc-spring/src/test/resources/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.xml new file mode 100644 index 00000000..6e0088f6 --- /dev/null +++ b/brpc-spring/src/test/resources/com/baidu/brpc/spring/AnnotationRpcXmlConfigurationTest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/brpc-spring/src/test/resources/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.xml b/brpc-spring/src/test/resources/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.xml new file mode 100644 index 00000000..9dc6f6c1 --- /dev/null +++ b/brpc-spring/src/test/resources/com/baidu/brpc/spring/HaRpcXmlConfigurationTest.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/brpc-spring/src/test/resources/com/baidu/brpc/spring/RpcXmlConfigurationTest.xml b/brpc-spring/src/test/resources/com/baidu/brpc/spring/RpcXmlConfigurationTest.xml new file mode 100644 index 00000000..56f420cc --- /dev/null +++ b/brpc-spring/src/test/resources/com/baidu/brpc/spring/RpcXmlConfigurationTest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/brpc-spring/src/test/resources/log4j2.xml b/brpc-spring/src/test/resources/log4j2.xml new file mode 100644 index 00000000..d026221c --- /dev/null +++ b/brpc-spring/src/test/resources/log4j2.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/cn/brpc_server.md b/docs/cn/brpc_server.md new file mode 100644 index 00000000..90e0ca65 --- /dev/null +++ b/docs/cn/brpc_server.md @@ -0,0 +1,93 @@ +## 标准协议/hulu协议/sofa协议 + +### 示例程序 +[RpcServerTest](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcServerTest.java) + +### 定义请求和响应结构proto +```java +package example; +option cc_generic_services = true; +option java_package="com.baidu.brpc.example.standard"; +option java_outer_classname="Echo"; + +message EchoRequest { + required string message = 1; +}; +message EchoResponse { + required string message = 1; +}; +service EchoService { + rpc Echo(EchoRequest) returns (EchoResponse); +}; +``` + +也支持使用jprotobuf方式定义的普通java类作为request/response,具体使用例子请见: +[jprotobuf](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf) +
在使用jprotobuf时,编译接口包时需要在maven的pom.xml中加上如下plugin: +```xml + + com.baidu + jprotobuf-precompile-plugin + 1.2.15 + + com.baidu + true + + + + compile + + precompile + + + + +``` + +### 定义java接口 +```java +public interface EchoService { + @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo") + Echo.EchoResponse echo(Echo.EchoRequest request); +} +``` +在java实现中,接口类并没有使用proto生成的EchoService,而是由业务自己去定义接口类,原因有两点: +- 为了多协议统一而做的通用设计,比如非proto协议场景。 +- 自定义的接口类,不用依赖controller对象,更符合RPC习惯。 + +BrpcMeta注解标记在接口类方法上,使用场景是 当java与c++通信时,java package与c++ namespace命名习惯不同,可以使用该注解来定制。BrpcMeta有两个属性: + +- 对于标准协议,serviceName默认是"包名"."类名",methodName是proto文件Service内对应方法名; +- 对于hulu协议,serviceName默认是类名,methodName是proto文件Service内对应方法index,index默认从0开始。 + +如果是java client和java server通信,BrpcMeta可以不填。当BrpcMeta不设置时,框架使用接口全名作为serviceName,方法名作为methodName。 + +### 接口实现类 + +```java +public class EchoServiceImpl implements EchoService { + private static final Logger LOG = LoggerFactory.getLogger(EchoServiceImpl.class); + + @Override + public Echo.EchoResponse echo(Echo.EchoRequest request) { + String message = request.getMessage(); + Echo.EchoResponse response = Echo.EchoResponse.newBuilder() + .setMessage(message).build(); + LOG.debug("EchoService.echo, request={}, response={}", + request.getMessage(), response.getMessage()); + return response; + } +} +``` + +对于标准协议和hulu协议有attachment功能,使用方式如下: + +```java +// 读取request attachment方法 +RpcContext rpcContext = RpcContext.getContext(); +ByteBuf attachment = rpcContext.getRequestBinaryAttachment(); +// 设置response attachment方法 +rpcContext.setResponseBinaryAttachment("hello".getBytes()); +``` + +server端request attachment和response attachment的byteBuf由框架去release,业务不需要手动释放。 \ No newline at end of file diff --git a/docs/cn/client.md b/docs/cn/client.md new file mode 100644 index 00000000..917016fa --- /dev/null +++ b/docs/cn/client.md @@ -0,0 +1,93 @@ +## 示例程序 +[RpcClientTest](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcClientTest.java) +## 接口类定义 +同server端,请见[server.md](https://github.com/baidu/brpc-java/blob/master/docs/cn/server.md) + +## 初始化RpcClient +RpcClient可传入四个参数: + +- 服务端地址:必选,支持多种naming方式,包括zookeeper://,consul://,list://,file://,dns://。 +- RpcClientOptions:可选,用于设置读写超时、交互协议、工作线程个数等重要参数。 +- 拦截器:可选,在发送请求和接受响应时,进行拦截。 + +在初始化RpcClient实例时,内部会建立连接池、创建netty acceptor线程池、io线程池、work线程池以及各种定时线程池。 + +所以应该在系统初始化时,就创建RpcClient实例,切勿在每次发送请求前去创建;而且对于同一个server,应该只初始化一个RpcClient实例。 + +## 生成接口代理类 + +```java +EchoService echoService = RpcClient.getProxy(rpcClient, EchoService.class); +``` + +接口代理类是线程安全的,只需要在系统初始化时,创建一个全局实例即可。 + +有了接口类后,就可以像普通函数调用一样,进行rpc调用。 + +## 异步调用 +### 1、定义异步callback + +通过实现RpcCallback接口的success/fail方法进行异步回调。 + +如果协议支持二进制attachment字段,需要release ResponseBinaryAttachment。 + +```java +RpcCallback callback = new RpcCallback() { + @Override + public void success(Echo.EchoResponse response) { + System.out.printf("async call EchoService.echo success, response=%s\n", + response.getMessage()); + if (RpcContext.getContext().getResponseBinaryAttachment() != null) { + System.out.println("attachment=" + + new String(RpcContext.getContext().getResponseBinaryAttachment().array())); + ReferenceCountUtil.release(RpcContext.getContext().getResponseBinaryAttachment()); + } + } + + @Override + public void fail(Throwable e) { + System.out.printf("async call EchoService.echo failed, %s\n", e.getMessage()); + } +}; +``` + +### 2、定义异步接口类 +```java +public interface EchoServiceAsync extends EchoService { + Future echo(Echo.EchoRequest request, RpcCallback callback); +} +``` + +异步接口类继承同步接口类,方法名要跟同步方法名一样,但比同步方法多一个callback参数。 + +异步接口类只需在client端定义,server端不需要。 + +### 3、生成异步接口代理类 +```java +EchoServiceAsync asyncEchoService = RpcClient.getProxy(rpcClient, EchoServiceAsync.class); +``` + +异步和同步可共用一个RpcClient实例。 + +异步调用跟同步不一样,异步调用返回Future对象,可调用future.get()进行同步等待。 + +如果使用场景是,同时发送多个异步请求出去,然后要等待所有server都返回后,再执行后续业务;这时候可以通过future.get()完成。 + +## 连接方式 + +支持连接池、单连接、短连接,默认是使用连接池。 + +## 负载均衡 +支持以下几种负载均衡: +- RANDOM:随机 +- ROUND_ROBIN:轮询 +- WEIGHT:基于权重的负载均衡,该负载均衡会记录server实例的成功、失败次数,尽量选择失败次数较少的实例。 +- FAIR:基于响应时间的负载均衡,该负载均衡会记录server实例平均响应时间,尽量选择响应时间短的实例。 + +## Naming方式 +支持以下几种naming方式: +- Zookeeper:格式如"zookeeper://127.0.0.1:2181/prefix" +- Consul +- LIST:格式如"list://127.0.0.1:8002" +- FILE:格式如"file://conf/server_list.conf",文件内容是一行一个ip:port +- DNS:格式如"dns://test.baidu.com" \ No newline at end of file diff --git a/docs/cn/composite_buffer.md b/docs/cn/composite_buffer.md new file mode 100644 index 00000000..a278061e --- /dev/null +++ b/docs/cn/composite_buffer.md @@ -0,0 +1,37 @@ +# [DynamicCompositeByteBuf](https://github.com/baidu/brpc-java/blob/master/brpc-java-core/src/main/java/com/baidu/brpc/buffer/DynamicCompositeByteBuf.java) +## 概述 +DynamicCompositeByteBuf用来在读socket数据时,处理网络粘包/拆包问题,并能做到零拷贝。 +其内部由多个netty ByteBuf组成,每次socket可读时,会append一个ByteBuf到DynamicCompositeByteBuf中; +然后从DynamicCompositeByteBuf读取一个完整的包,并移除不再使用的ByteBuf。 + +## 为什么不直接使用netty提供的CompositeByteBuf? +* CompositeByteBuf对引用计数不太灵活(为了兼容ByteBuf接口),每一次调用retainedSlice/readRetainedSlice, +都会增加CompositeByteBuf的引用计数,而不是增加内部ByteBuf引用计数。 +* DynamicCompositeByteBuf是直接增加内部ByteBuf引用计数,本身并没有全局引用计数。 +* CompositeByteBuf不会实时删除已读的ByteBuf,DynamicCompositeByteBuf会。 + +## 主要功能及设计 +### 内部数据结构 +* ArrayDeque,元素是netty ByteBuf。当有新buffer时,会加入队列;当从DynamicCompositeByteBuf读取数据后,会从队列中移除。 +* readableBytes,所有ByteBuf的可读字节数。 + +## addBuffer +将ByteBuf直接加入队列,并增加readableBytes。 +ByteBuf的引用计数并没有增加,其生命周期由DynamicCompositeByteBuf管理。 + +## retainedSlice +从DynamicCompositeByteBuf中截取length个字节,并返回一个netty CompositeByteBuf。 +该函数会遍历队列中的ByteBuf,对ByteBuf进行retainedSlice并加入CompositeByteBuf,直到readableBytes达到length为止。 +因此队列中返回的ByteBuf的refCnt会加1,且并不会出队,也不会改变DynamicCompositeByteBuf的readableBytes大小。 +该功能主要用于读取请求包的header部分,遍历所有协议,尝试解析协议header部分,并判断出是哪个协议。 + +## skipBytes +移除length个字节对应的ByteBuf,并release调移除的ByteBuf。 +该函数主要用于把请求的header长度从DynamicCompositeByteBuf移除。 + +## readRetainedSlice +从DynamicCompositeByteBuf中截取length个字节,并移除对应的ByteBuf。 +如果某个ByteBuf完全被返回,则会从DynamicCompositeByteBuf中移除,并不增加ByteBuf的refCnt。 +如果某个ByteBuf部分被返回,则会调用ByteBuf的readRetainedSlice,增加ByteBuf引用计数和readerIndex, +着是ByteBuf并不会从DynamicCompositeByteBuf移除,而是被两边同时引用。 +该函数主要用于把请求的body部分的buffer截取出来,由后续的工作线程来解析并处理。 diff --git a/docs/cn/extension.md b/docs/cn/extension.md new file mode 100644 index 00000000..c1727282 --- /dev/null +++ b/docs/cn/extension.md @@ -0,0 +1,88 @@ +# 扩展新协议 +## 总体步骤: +* 实现AbstractProtocol类的相关方法。 +* 实现ProtocolFactory类,为新协议提供Factory。 +* 利用spi机制,在resources/META-INF/services目录下创建名为com.baidu.brpc.protocol.ProtocolFactory的文件, +内容是Factory全路径类名。 + +## client和server共同需要实现的方法: +```java +/** + * 客户端/服务端解析请求包成header+body buffer + * @param in 输入byte buf + * @return header+body buffer + * @throws BadSchemaException header格式不对 + * @throws TooBigDataException body太大 + * @throws NotEnoughDataException 可读长度不够,由于粘包拆包问题。 + */ +Object decode(ChannelHandlerContext ctx, DynamicCompositeByteBuf in, boolean isDecodingRequest) + throws BadSchemaException, TooBigDataException, NotEnoughDataException; + +/** + * 该协议是否可以和其他协议共存。 + * @return true可以共存,false不能共存。 + */ +boolean isCoexistence(); +``` + +## client端需实现的方法: +```java +/** + * 客户端序列化请求对象 + * @param request 待发送给服务端的对象 + * @throws Exception 序列化异常 + */ +ByteBuf encodeRequest(Request request) throws Exception; + +/** + * 客户端反序列化rpc响应 + * @param packet header & body的buf + * @param ctx netty channel context + * @throws Exception 反序列化异常 + */ +RpcResponse decodeResponse(Object packet, ChannelHandlerContext ctx) throws Exception; + +/** + * 连接归还的时机 + * @return true代表请求发送后立即归还连接,false表示收到响应后归还。 + */ +boolean returnChannelBeforeResponse(); +``` + +## server端需要实现的方法: +```java +/** + * 服务端反序列化rpc请求 + * @param packet header & body的buf + * @return 输出对象 + */ +Request decodeRequest(Object packet) throws Exception; + +/** + * 服务端序列化返回结果。 + * @param response 服务端要返回给客户端的对象 + * @throws Exception 序列化异常 + */ +ByteBuf encodeResponse(Request request, Response response) throws Exception; +``` + +## 扩展新的服务注册发现 +* 实现NamingService接口。 +* 实现NamingServiceFactory接口。 +* 利用spi机制,在resources/META-INF/services目录下创建名为com.baidu.brpc.naming.NamingServiceFactory的文件, + 内容是Factory全路径类名。 + +## 新增负载均衡实现 +* 实现LoadBalanceStrategy接口。 +* 实现LoadBalanceFactory接口。 +* 利用spi机制,在resources/META-INF/services目录下创建名为com.baidu.brpc.client.loadbalance.LoadBalanceFactory的文件, + 内容是Factory全路径类名。 + +## 新增拦截器 +* 实现Interceptor接口 +* 在初始化RpcClient或RpcServer时,传入interceptors参数中。 + +## 新增限流算法实现 +* 实现CurrentLimiter接口。 +* 创建CurrentLimitInterceptor实例。 +* 在初始化RpcClient或RpcServer时,传入interceptors参数中。 diff --git a/docs/cn/fast-future-store.jpg b/docs/cn/fast-future-store.jpg new file mode 100644 index 00000000..950821a3 Binary files /dev/null and b/docs/cn/fast-future-store.jpg differ diff --git a/docs/cn/fastfuturestore.md b/docs/cn/fastfuturestore.md new file mode 100644 index 00000000..802de25e --- /dev/null +++ b/docs/cn/fastfuturestore.md @@ -0,0 +1,43 @@ +`FastFutureStore`是一个并发安全的、比`ConcurrentHashMap`更快的k-v存储组件,其实现思路为使用数组作为底层存储结构,同时将key的一部分bit解析为数组下标以达到快速查找、插入的目的,因此使用此组件硬性要求是key只能为long类型。Benchmark显示在多线程环境下,`FastFutureStore`比 JDK1.8 的`ConcurrentHashMap`快20% ~ 50%。 + + + +## 实现原理 + +`FastFutureStore`会使用数组和`ConcurrentHashMap`来存储`RpcFuture`对象,如果数组容量不足则会降级存储至Map中。 + +### 在logId中存储对象位置信息 + +调用`put(RpcFuture)`方法添加对象时会返回一个long类型的logId,其组成结构如下图所示: + +![](fast-future-store.jpg) + +第 0 ~ 62 位用来存储数组下标,第 63 位表示此logId存储位置(数组或ConcurrentHashMap), 最高位为保留位无特殊含义; + +### 查找操作 + +S1: 判断logId第63位是否为1, 如果是则直接从Map中取出对象, 否则进入S2; + +S2: 将0 ~ 62位解析为数组下标, 验证下标合法后,CAS直接从数组中取出并删除目标对象,返回; + + + +### 添加操作 + +`FastFutureStore`维护了一个原子类型的计数器`slotCounter`, 初始值为0, 当调用put方法添加对象时会执行以下步骤: + +S1: 将`slotCounter`做`getAndIncrement()`操作,把返回值与数组最大容量执行取余操作,其结果就是此对象的数组下标`slot`; + +S2: 检查`slotCounter`是否大于等于`0x1 << 62`, 为真则重置为0; + +S3: 使用CAS操作尝试将`array[slot]`设置为目标对象,当且仅当`slot`对应的元素为null时CAS才会成功; + +S4: 如果成功,则返回`slotCounter`值; 如果失败,说明此位置已被占用,回到S1; + +S5: 如果循环次数达到了数组最大容量,说明此时数组已满,则将对象以`slotCounter`为key降级存储至`ConcurrentHashMap`中,同时将 storage flag bit置为1; + + + + + +因为性能的原因,`FastFutreStore`不会自动扩容底层数组,而是使用`ConcurrentHashMap`做为容量不足时的备用存储方式,因此数组容量的大小至关重要,过大会浪费内存,过小会因空间不足而退化成Map。建议根据client端的最大请求qps来设置此值。 \ No newline at end of file diff --git a/docs/cn/http_server.md b/docs/cn/http_server.md new file mode 100644 index 00000000..037c65d9 --- /dev/null +++ b/docs/cn/http_server.md @@ -0,0 +1,20 @@ +## 示例程序 + +[brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http](https://github.com/baidu/brpc-java/tree/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http) + +## 支持的content-type类型 +* application/json +* application/proto + +## 定义application json/proto接口类 + +```java +public interface HelloWorldService { + @BrpcMeta(serviceName = "HelloWorldService", methodName = "hello") + String hello(String request); +} +``` +* 使用application/json或者application/proto时,uri是serviceName + "/" + methodName,跟baidu-rpc c++版本一致。 +* 当BrpcMeta不设置时,框架使用接口全名作为serviceName,方法名作为methodName。 +* 当body是proto时,也支持使用jprotobuf方式定义的普通java类作为request/response。 + diff --git a/docs/cn/nshead_server.md b/docs/cn/nshead_server.md new file mode 100644 index 00000000..6fc9a905 --- /dev/null +++ b/docs/cn/nshead_server.md @@ -0,0 +1,38 @@ +## 示例程序 + +[RpcServerTest](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcServerTest.java) + +## 定义请求和响应类 +目前序列化方式使用protobuf,也支持使用jprotobuf方式定义的普通java类作为request/response, +具体使用例子请见[jprotobuf](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/jprotobuf/RpcServerTest.java)。 + +```proto +package example; +option cc_generic_services = true; +option java_package="com.baidu.brpc.example.standard"; +option java_outer_classname="Echo"; + +message EchoRequest { + required string message = 1; +}; +message EchoResponse { + required string message = 1; +}; +service EchoService { + rpc Echo(EchoRequest) returns (EchoResponse); +}; +``` + + +## 定义java接口 + +nshead接口类 +```java +public interface EchoService { + @NSHeadMeta(provider = "custom-provider") + Echo.EchoResponse echo(Echo.EchoRequest request); +} +``` + +* NSHeadMeta标记在接口方法上,用于设置NSHead相关属性,包括provider、id、version,默认可以不填。 +* nshead协议server端只支持一个接口一个方法,因为nshead协议中没有字段来唯一定位一个方法。 \ No newline at end of file diff --git a/docs/cn/server.md b/docs/cn/server.md new file mode 100644 index 00000000..19da3a81 --- /dev/null +++ b/docs/cn/server.md @@ -0,0 +1,61 @@ +## 示例程序 + +- [标准协议/hulu协议/sofa协议](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/standard/RpcServerTest.java) +- [nshead协议](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/nshead/RpcServerTest.java) +- [http协议](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/http/proto/RpcServerTest.java) + +## 定义接口类以及实现类 + +- [标准协议/hulu协议/sofa协议](https://github.com/baidu/brpc-java/blob/master/docs/cn/brpc_server.md) +- [nshead协议](https://github.com/baidu/brpc-java/blob/master/docs/cn/nshead_server.md) +- [http协议](https://github.com/baidu/brpc-java/blob/master/docs/cn/http_server.md) + +## 定义Main类 +server端启动主要分两步: + +- 配置RpcServerOptions:配置io线程数、工作线程数、协议类型等。 +- 初始化RpcServer实例:所需参数为端口、RpcServerOptions(可选)、以及interceptor(可选)。 +- 注册服务实例。 + +具体代码如下: + +```java +public class RpcServerTest { + public static void main(String[] args) throws InterruptedException { + int port = 8002; + if (args.length == 1) { + port = Integer.valueOf(args[0]); + } + + RpcServerOptions options = new RpcServerOptions(); + options.setReceiveBufferSize(64 * 1024 * 1024); + options.setSendBufferSize(64 * 1024 * 1024); + final RpcServer rpcServer = new RpcServer(port, options); + rpcServer.registerService(new EchoServiceImpl()); + rpcServer.start(); + + // make server keep running + synchronized (RpcServerTest.class) { + try { + RpcServerTest.class.wait(); + } catch (Throwable e) { + } + } + } +} +``` + +## 限流 +server通过CurrentLimitInterceptor实现限流,目前支持两种限流算法: + +- [计数器算法](https://github.com/baidu/brpc-java/blob/master/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CounterCurrentLimiter.java) +- [令牌桶算法](https://github.com/baidu/brpc-java/blob/master/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/TokenBucketCurrentLimiter.java) + +如果不能满足需求,业务也可以实现自己的限流算法,只需实现[CurrentLimiter.java](https://github.com/baidu/brpc-java/blob/master/brpc-java-core/src/main/java/com/baidu/brpc/server/currentlimit/CurrentLimiter.java)这个接口即可。 + +启用限流功能代码示例: + +```java +RpcServer server = new RpcServer(8000); +server.getInterceptors().add(new CurrentLimitInterceptor(new TokenBucketCurrentLimiter(500, 500))); +``` \ No newline at end of file diff --git a/docs/cn/server_push.md b/docs/cn/server_push.md new file mode 100644 index 00000000..734a1e8b --- /dev/null +++ b/docs/cn/server_push.md @@ -0,0 +1,70 @@ +## 服务端推送(server push)协议 +服务端推送功能的主要原理为, 在客户端启动时会向服务端注册clientName并保持长连接,服务端通过clientName向指定的客户端推送消息 + + +### 示例程序 +[RpcServerTest](https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcServerPushTest.java +https://github.com/baidu/brpc-java/blob/master/brpc-java-examples/brpc-java-core-examples/src/main/java/com/baidu/brpc/example/push/RpcClientPushTest.java) + + +### 使用默认的server push协议 +client端: +首先定义client用于接收消息接口 +```java +public interface UserPushApi { + + PushResult clientReceive(String extra, PushData data); + +} +``` +与服务端建立连接 +```java +RpcClientOptions clientOption = new RpcClientOptions(); +clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); + +// 指定clientName +clientOption.setClientName("c1"); + +// 创建客户端 c1 +RpcClient rpcClient = new RpcClient(serviceUrl, clientOption); +// 首先建立一个普通rpc client服务, 与后端建立起连接 +EchoService service1 = BrpcProxy.getProxy(rpcClient, EchoService.class); +// 注册实现push方法 +rpcClient.registerPushService(new UserPushApiImpl()); + +``` + + 服务端: + 继承client的接口,增加一个带有clientName的同名方法 + ```java +public interface ServerSideUserPushApi extends UserPushApi { + + // server端接口, 多一个clientName参数 + PushResult clientReceive(String clientName, String extra, PushData data); + +} + ``` + 服务端向c1客户端发请求 + ```java +RpcServerOptions options = new RpcServerOptions(); +options.setProtocolType(Options.ProtocolType.PROTOCOL_SERVER_PUSH_VALUE); +rpcServer = new RpcServer(port, options); +rpcServer.registerService(new EchoServiceImpl()); // 普通rpc服务 +// get push api +ServerSideUserPushApi proxyPushApi = BrpcPushProxy.getProxy(rpcServer, ServerSideUserPushApi.class); +rpcServer.start(); +// send push data to c1 +PushData p1 = new PushData(); +PushResult pushResultI = proxyPushApi.clientReceive("c1","abc", p1); + + ``` + +### 多个client实例的情况 +当多个client用相同的clientName注册到服务端的时候, 服务端推送时,只会向其中一个client发送请求 + + +### 自定义 server push 协议 +如果要自定义server push 协议实现, 可以通过实现相关接口实现 +实现ServerPushProtocol、ServerPushPacket和SPHead , 然后通过自定义ServerPushProtocolFactory和提供com.baidu.brpc.protocol +.ProtocolFactory 文件进行加载 + diff --git a/docs/cn/spring.md b/docs/cn/spring.md new file mode 100644 index 00000000..29ef4d50 --- /dev/null +++ b/docs/cn/spring.md @@ -0,0 +1,88 @@ +# Spring集成支持 +## 引入maven依赖 +```xml + + com.baidu + brpc-spring-starter + 2.4.0 + +``` +## 接口声明跟非Spring用法一样 +## 在application.yml中添加配置: +```yaml +brpc: + global: + naming: + namingServiceUrl: zookeeper://127.0.0.1:2181/examples + namingServiceFactory: com.baidu.brpc.naming.zookeeper.ZookeeperNamingFactory + group: "normal" + version: 1.0.0 + ignoreFailOfNamingService: false + server: + port: 8002 + workThreadNum: 1 + ioThreadNum: 1 + client: + workThreadNum: 1 + ioThreadNum: 1 + custom: + com.baidu.brpc.example.springboot.api.EchoService: + naming: + version: 2.0.0 + com.baidu.brpc.example.springboot.api.AsyncEchoService: + naming: + version: 2.0.0 +``` +* brpc.global是默认配置,brpc.custom是具体接口的自定义配置。 +* brpc.global.server只有在使用RpcServer时才需要。 +* brpc.global.client只有在使用RpcClient时才需要。 + +## Server端使用@RpcExporter暴露服务 +```java +@RpcExporter +public class EchoServiceImpl implements EchoService { + @Override + public EchoResponse echo(EchoRequest request) { + String message = request.getMessage(); + EchoResponse response = new EchoResponse(); + response.setMessage(message); + return response; + } +} +``` +## Client端使用@RpcProxy生成接口代理对象 +```java +@Service +public class EchoFacadeImpl implements EchoFacade { + @RpcProxy + private EchoService echoService; + + /** + * async service interface proxy will create new RpcClient, + * not used RpcClient of sync interface proxy. + */ + @RpcProxy + private AsyncEchoService echoService3; + + public EchoResponse echo(EchoRequest request) { + System.out.println(echoService.hashCode()); + return echoService.echo(request); + } + + public Future echo3(EchoRequest request) { + System.out.println(echoService3.hashCode()); + Future future = echoService3.echo(request, new RpcCallback() { + @Override + public void success(EchoResponse response) { + System.out.println(response.getMessage()); + } + + @Override + public void fail(Throwable e) { + e.printStackTrace(); + } + }); + return future; + } +} +``` diff --git a/examples/demo-api/pom.xml b/examples/demo-api/pom.xml deleted file mode 100644 index 7270a1ad..00000000 --- a/examples/demo-api/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - examples - 0.1.0-SNAPSHOT - - - demo-api - - - - com.baidu.cloud - spring-cloud-baidu-thirdparty-commons - 2022.2.0 - true - - - diff --git a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/UserService.java b/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/UserService.java deleted file mode 100644 index 69b6d2a7..00000000 --- a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/UserService.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.api; - -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.DeleteMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PathVariable; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PutMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestParam; - -import java.util.List; -import java.util.Map; - -/** - * 默认情况无需增加SpringMVC注解, - * 服务端对外提供Rest服务时才需要添加SpringMVC注解 - */ -@RequestMapping("/user") -public interface UserService { - - /** - * 单基本类型参数示例 - * - * @param userId - * @return - */ - @GetMapping - User getUser(@RequestParam("userId") Long userId); - - @PutMapping - User updateUser(@RequestBody User user); - - /** - * 返回值void - * - * @param userId - */ - @DeleteMapping - void deleteUser(@RequestParam("userId")Long userId); - - @PostMapping - Long saveUser(@RequestBody User user); - - /** - * 请求和响应参数均为空 - */ - @GetMapping("/connect") - void connect(); - - /** - * 多参数 客户端需配置使用pb2-java序列化模式 - java api:ServiceConfig.setSerializeMode("pb2-java"); - spring boot 配置: - * starlight.client.config.default.serializeMode=pb2-java - * - * @param userId - * @param user - * @return - */ - @PostMapping("/multiparams") - User multiParams(@RequestParam("userId") Long userId, @RequestBody User user); - - /** - * 返回List集合类 客户端需配置使用pb2-java序列化模式 - java api:ServiceConfig.setSerializeMode("pb2-java"); - spring boot 配置: - * starlight.client.config.default.serializeMode=pb2-java - * - * @return - */ - @GetMapping("/list") - List allUsers(); - - @GetMapping("/name/{userId}") - String userName(@PathVariable("userId") Long userId); - - /** - * 返回map集合类 客户端需配置使用pb2-java序列化模式 - java api:ServiceConfig.setSerializeMode("pb2-java"); - spring boot 配置: - * starlight.client.config.default.serializeMode=pb2-java - * - * @param userId - * @param user - * @return - */ - @PostMapping("/map") - Map userMap(@RequestParam("userId") Long userId, @RequestBody User user); - - /** - * 方法抛出异常 - * - * @param userId - * @return - */ - @GetMapping("/exception") - User userExp(Long userId); -} diff --git a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Address.java b/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Address.java deleted file mode 100644 index d25cb362..00000000 --- a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Address.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.api.model; - -public class Address { - private String address; - - public Address(String address) { - this.address = address; - } - - public Address() {} - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("Address{"); - sb.append("address='").append(address).append('\''); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file diff --git a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/ExtInfo.java b/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/ExtInfo.java deleted file mode 100644 index 36d6b988..00000000 --- a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/ExtInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.api.model; - -public class ExtInfo { - private String key; - - private String value; - - public ExtInfo() { - - } - - public ExtInfo(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ExtInfo{"); - sb.append("key='").append(key).append('\''); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file diff --git a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Gender.java b/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Gender.java deleted file mode 100644 index 9a653100..00000000 --- a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/Gender.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.api.model; - -public enum Gender { - MALE("male"), FEMALE("female"), NONE("none"); - - private final String name; - - Gender(String name) { - this.name = name; - } -} \ No newline at end of file diff --git a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/User.java b/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/User.java deleted file mode 100644 index f55df694..00000000 --- a/examples/demo-api/src/main/java/com/baidu/cloud/demo/api/model/User.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.api.model; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -public class User { - - private long userId; - - private Gender gender; - - private int age; - - @Deprecated - private String userName; - - private double balance; - - private float salary; - - private Address address; - - private List tags; - - private List extInfos; // proto2 not support map, please transform to list - - private boolean alive; - - private String info; - - private Map map; - - private Date date; - - public User() { - - } - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public List getExtInfos() { - return extInfos; - } - - public void setExtInfos(List extInfos) { - this.extInfos = extInfos; - } - - public Gender getGender() { - return gender; - } - - public void setGender(Gender gender) { - this.gender = gender; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public float getSalary() { - return salary; - } - - public void setSalary(float salary) { - this.salary = salary; - } - - public Address getAddress() { - return address; - } - - public void setAddress(Address address) { - this.address = address; - } - - public boolean isAlive() { - return alive; - } - - public void setAlive(boolean alive) { - this.alive = alive; - } - - public String getInfo() { - return info; - } - - public void setInfo(String info) { - this.info = info; - } - - public Map getMap() { - return map; - } - - public void setMap(Map map) { - this.map = map; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("User{"); - sb.append("userId=").append(userId); - sb.append(", sex=").append(gender); - sb.append(", age=").append(age); - sb.append(", userName='").append(userName).append('\''); - sb.append(", balance=").append(balance); - sb.append(", salary=").append(salary); - sb.append(", address=").append(address); - sb.append(", tags=").append(tags); - sb.append(", extInfos=").append(extInfos); - sb.append(", alive=").append(alive); - sb.append(", info='").append(info).append('\''); - sb.append(", map='").append(map).append('\''); - sb.append('}'); - return sb.toString(); - } -} diff --git a/examples/java-examples/demo-consumer/pom.xml b/examples/java-examples/demo-consumer/pom.xml deleted file mode 100644 index e6b6b08e..00000000 --- a/examples/java-examples/demo-consumer/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - java-examples - 0.1.0-SNAPSHOT - - demo-consumer - - - - com.baidu.cloud - starlight-all - 2022.2.0 - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - diff --git a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/AsyncGenericConsumerApp.java b/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/AsyncGenericConsumerApp.java deleted file mode 100644 index c6608e86..00000000 --- a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/AsyncGenericConsumerApp.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer; - -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.generic.AsyncGenericService; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; -import com.baidu.cloud.starlight.core.utils.PojoJsonUtils; - -import java.lang.reflect.Type; -import java.util.Map; -import java.util.concurrent.Future; - -public class AsyncGenericConsumerApp { - - public static void main(String[] args) throws Exception { - // 创建Client - TransportConfig config = new TransportConfig(); // 传输配置 - StarlightClient starlightClient = new SingleStarlightClient("localhost", 8005, config); - starlightClient.init(); - - // 引用服务 - ServiceConfig clientConfig = new ServiceConfig(); // 服务配置 - clientConfig.setProtocol("brpc"); - clientConfig.setServiceId("com.baidu.cloud.demo.api.UserService"); - - // 生成代理 - JDKProxyFactory proxyFactory = new JDKProxyFactory(); - AsyncGenericService userService = - proxyFactory.getProxy(AsyncGenericService.class, clientConfig, starlightClient); - - // 发起调用 - Future resultFuture = userService.$invokeFuture("getUser", new Object[] {1L}); - @SuppressWarnings("unchecked") - Map result = (Map) resultFuture.get(); - User user = (User) PojoJsonUtils.realize(new Object[] {result}, new Type[] {User.class})[0]; - System.out.println(user.toString()); - - // 销毁client - starlightClient.destroy(); - - System.exit(0); - } -} diff --git a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/DemoConsumerApp.java b/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/DemoConsumerApp.java deleted file mode 100644 index 07ee86ec..00000000 --- a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/DemoConsumerApp.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; - -public class DemoConsumerApp { - - public static void main(String[] args) { - // 创建Client - TransportConfig config = new TransportConfig(); // 传输配置 - StarlightClient starlightClient = new SingleStarlightClient("localhost", 8005, config); - starlightClient.init(); - - // 引用服务 - ServiceConfig clientConfig = new ServiceConfig(); // 服务配置 - clientConfig.setProtocol("brpc"); - // clientConfig.setSerializeMode("pb2-java"); - // clientConfig.setServiceId("com.baidu.cloud.rpc.benchmarks.service.EchoService"); - - // 生成代理 - JDKProxyFactory proxyFactory = new JDKProxyFactory(); - UserService userService = proxyFactory.getProxy(UserService.class, clientConfig, starlightClient); - - // 发起调用 - User user = userService.getUser(1L); - System.out.println(user.toString()); - - // 销毁client - starlightClient.destroy(); - - System.exit(0); - } -} diff --git a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/GenericConsumerApp.java b/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/GenericConsumerApp.java deleted file mode 100644 index 36ce5654..00000000 --- a/examples/java-examples/demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/GenericConsumerApp.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer; - -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.generic.GenericService; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; -import com.baidu.cloud.starlight.core.utils.PojoJsonUtils; - -import java.lang.reflect.Type; -import java.util.LinkedHashMap; -import java.util.Map; - -public class GenericConsumerApp { - - public static void main(String[] args) throws Exception { - // 创建Client - TransportConfig config = new TransportConfig(); // 传输配置 - StarlightClient starlightClient = new SingleStarlightClient("localhost", 8005, config); - starlightClient.init(); - - // 引用服务 - ServiceConfig clientConfig = new ServiceConfig(); // 服务配置 - clientConfig.setProtocol("brpc"); - clientConfig.setServiceId("com.baidu.cloud.demo.api.UserService"); - - // 生成代理 - JDKProxyFactory proxyFactory = new JDKProxyFactory(); - GenericService userService = proxyFactory.getProxy(GenericService.class, clientConfig, starlightClient); - - // 发起调用 - @SuppressWarnings("unchecked") - Map result = (LinkedHashMap) userService.$invoke("getUser", new Object[] {1L}); - User user = (User) PojoJsonUtils.realize(new Object[] {result}, new Type[] {User.class})[0]; - System.out.println(user.toString()); - - // 销毁client - starlightClient.destroy(); - - System.exit(0); - } -} diff --git a/examples/java-examples/demo-provider/pom.xml b/examples/java-examples/demo-provider/pom.xml deleted file mode 100644 index 8a6cec65..00000000 --- a/examples/java-examples/demo-provider/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - java-examples - 0.1.0-SNAPSHOT - - - demo-provider - - - - com.baidu.cloud - starlight-all - 2022.2.0 - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - - diff --git a/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/DemoProviderApp.java b/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/DemoProviderApp.java deleted file mode 100644 index e5c7b2ac..00000000 --- a/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/DemoProviderApp.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.provider.service.UserServiceImpl; -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.DefaultStarlightServer; - -public class DemoProviderApp { - - public static void main(String[] args) { - // 初始化server - TransportConfig transportConfig = new TransportConfig(); - StarlightServer starlightServer = new DefaultStarlightServer("localhost", 8005, transportConfig); - starlightServer.init(); - - // 暴露接口信息 - ServiceConfig serviceConfig = new ServiceConfig(); - starlightServer.export(UserService.class, new UserServiceImpl(), serviceConfig); - - // 开启服务 - starlightServer.serve(); - - synchronized (DemoProviderApp.class) { - try { - DemoProviderApp.class.wait(); - } catch (Throwable e) { - } - } - } -} \ No newline at end of file diff --git a/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java b/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java deleted file mode 100644 index 537421d1..00000000 --- a/examples/java-examples/demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider.service; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.Address; -import com.baidu.cloud.demo.api.model.ExtInfo; -import com.baidu.cloud.demo.api.model.Gender; -import com.baidu.cloud.demo.api.model.User; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class UserServiceImpl implements UserService { - - @Override - public User getUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - user.setGender(Gender.MALE); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("Beijing"))); - return user; - } - - @Override - public User updateUser(User user) { - return user; - } - - @Override - public void deleteUser(Long userId) { - System.out.println("Delete user {" + userId + "}"); - } - - @Override - public Long saveUser(User user) { - return user.getUserId(); - } - - @Override - public void connect() { - System.out.println("Connect Success"); - } - - @Override - public User multiParams(Long userId, User user) { - if (user == null) { - user = new User(); - } - user.setUserId(userId == null ? 0L : userId); - return user; - } - - @Override - public List allUsers() { - User user = new User(); - user.setUserId(1l); - user.setUserName("u1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("heibei"))); - - User user2 = new User(); - user2.setUserId(2l); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - List users = new LinkedList<>(); - users.add(user); - users.add(user2); - return users; - } - - @Override - public String userName(Long userId) { - return "User1"; - } - - @Override - public Map userMap(Long userId, User user) { - - User user2 = new User(); - user2.setUserId(2L); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - return Collections.singletonMap(2L, user2); - } - - @Override - public User userExp(Long userId) { - if (userId > 1000) { - throw new StackOverflowError(); - } - - if (userId > 100) { - throw new NullPointerException(); - } - - if (userId > 10) { - throw new RuntimeException("Exception Occur"); - } - - return getUser(userId); - - } -} diff --git a/examples/java-examples/pom.xml b/examples/java-examples/pom.xml deleted file mode 100644 index f38f59de..00000000 --- a/examples/java-examples/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - java-examples - 0.1.0-SNAPSHOT - pom - - demo-provider - demo-consumer - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - diff --git a/examples/pom.xml b/examples/pom.xml deleted file mode 100644 index 71446816..00000000 --- a/examples/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - examples - 0.1.0-SNAPSHOT - pom - - demo-api - java-examples - spring-boot-examples - spring-cloud-examples - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - diff --git a/examples/spring-boot-examples/pom.xml b/examples/spring-boot-examples/pom.xml deleted file mode 100644 index 1207099d..00000000 --- a/examples/spring-boot-examples/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.0.7.RELEASE - - - - - com.baidu.cloud - spring-boot-examples - 0.1.0-SNAPSHOT - pom - - springboot-demo-provider - springboot-demo-consumer - - - - 1.8 - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - diff --git a/examples/spring-boot-examples/springboot-demo-consumer/pom.xml b/examples/spring-boot-examples/springboot-demo-consumer/pom.xml deleted file mode 100644 index fca869ff..00000000 --- a/examples/spring-boot-examples/springboot-demo-consumer/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - spring-boot-examples - 0.1.0-SNAPSHOT - - springboot-demo-consumer - - 8 - 8 - - - - - com.baidu.cloud - spring-cloud-starter-baidu-starlight - 2022.2.0 - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - - diff --git a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringBootConsumerApp.java b/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringBootConsumerApp.java deleted file mode 100644 index 6ec3a552..00000000 --- a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringBootConsumerApp.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer; - -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@StarlightScan -public class SpringBootConsumerApp { - - public static void main(String[] args) { - SpringApplication.run(SpringBootConsumerApp.class, args); - } - -} diff --git a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java b/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java deleted file mode 100644 index 3400f46a..00000000 --- a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer.service; - -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.DeleteMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PathVariable; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PutMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestParam; - -import java.util.List; -import java.util.Map; - -/** - * Starlight Rest 风格支持 - * - * @Date 2022/9/28 21:16 - * @Created by liuruisen - */ -@RequestMapping("/user") -public interface UserRestService { - - @GetMapping - User getUser(@RequestParam("userId") Long userId); - - @PutMapping - User updateUser(@RequestBody User user); - - @DeleteMapping - void deleteUser(@RequestParam("userId") Long userId); - - @PostMapping - Long saveUser(@RequestBody User user); - - @GetMapping("/connect") - void connect(); - - @PostMapping("/multiparams") - User multiParams(@RequestParam("userId") Long userId, @RequestBody User user); - - @GetMapping("/list") - List allUsers(); - - @GetMapping("/name/{userId}") - String userName(@PathVariable("userId") Long userId); - - @PostMapping("/map") - Map userMap(@RequestParam("userId") Long userId, @RequestBody User user); - - @GetMapping("/exception") - User userExp(Long userId); -} diff --git a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java b/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java deleted file mode 100644 index cabf80ce..00000000 --- a/examples/spring-boot-examples/springboot-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer.service.impl; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.demo.consumer.service.UserRestService; -import com.baidu.cloud.starlight.springcloud.client.annotation.RpcProxy; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -import java.util.List; -import java.util.Map; - -/** - * @Date 2022/9/28 21:23 - * @Created by liuruisen - */ -@RpcService -public class UserRestServiceImpl implements UserRestService { - - /** - * 不依赖注册发现,直连方式调用 - */ - @RpcProxy(remoteUrl = "localhost:8777", protocol = "brpc") - private UserService userService; - - /** - * 不依赖注册发现,直连方式调用 - */ - @RpcProxy(remoteUrl = "localhost:8777", protocol = "springrest") - private UserService restUserService; - - @Override - public User getUser(Long userId) { - System.out.println("springrest result: " + restUserService.getUser(userId)); - return userService.getUser(userId); - } - - @Override - public User updateUser(User user) { - return userService.updateUser(user); - } - - @Override - public void deleteUser(Long userId) { - userService.deleteUser(userId); - } - - @Override - public Long saveUser(User user) { - return userService.saveUser(user); - } - - @Override - public void connect() { - userService.connect(); - } - - @Override - public User multiParams(Long userId, User user) { - return userService.multiParams(userId, user); - } - - @Override - public List allUsers() { - return userService.allUsers(); - } - - @Override - public String userName(Long userId) { - return userService.userName(userId); - } - - @Override - public Map userMap(Long userId, User user) { - return userService.userMap(userId, user); - } - - @Override - public User userExp(Long userId) { - return userService.userExp(userId); - } -} diff --git a/examples/spring-boot-examples/springboot-demo-consumer/src/main/resources/application.yml b/examples/spring-boot-examples/springboot-demo-consumer/src/main/resources/application.yml deleted file mode 100644 index ed423e3f..00000000 --- a/examples/spring-boot-examples/springboot-demo-consumer/src/main/resources/application.yml +++ /dev/null @@ -1,8 +0,0 @@ -starlight: - server: - enable: true - port: 8666 -# client: - # config: - # default: - # serialize-mode: pb2-java \ No newline at end of file diff --git a/examples/spring-boot-examples/springboot-demo-provider/pom.xml b/examples/spring-boot-examples/springboot-demo-provider/pom.xml deleted file mode 100644 index 14a5fb6d..00000000 --- a/examples/spring-boot-examples/springboot-demo-provider/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - spring-boot-examples - 0.1.0-SNAPSHOT - - - springboot-demo-provider - - - - com.baidu.cloud - spring-cloud-starter-baidu-starlight - 2022.2.0 - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - - diff --git a/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringBootProviderApp.java b/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringBootProviderApp.java deleted file mode 100644 index d01e35f8..00000000 --- a/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringBootProviderApp.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider; - -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@StarlightScan -public class SpringBootProviderApp { - - public static void main(String[] args) { - SpringApplication.run(SpringBootProviderApp.class, args); - } -} diff --git a/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java b/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java deleted file mode 100644 index 9b97461b..00000000 --- a/examples/spring-boot-examples/springboot-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider.service; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.Address; -import com.baidu.cloud.demo.api.model.ExtInfo; -import com.baidu.cloud.demo.api.model.Gender; -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -@RpcService -public class UserServiceImpl implements UserService { - - @Override - public User getUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - user.setGender(Gender.MALE); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("Beijing"))); - return user; - } - - @Override - public User updateUser(User user) { - return user; - } - - @Override - public void deleteUser(Long userId) { - System.out.println("Delete user {" + userId + "}"); - } - - @Override - public Long saveUser(User user) { - return user.getUserId(); - } - - @Override - public void connect() { - System.out.println("Connect Success"); - } - - @Override - public User multiParams(Long userId, User user) { - if (user == null) { - user = new User(); - } - user.setUserId(userId == null ? 0L : userId); - return user; - } - - @Override - public List allUsers() { - User user = new User(); - user.setUserId(1l); - user.setUserName("u1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("heibei"))); - - User user2 = new User(); - user2.setUserId(2l); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - List users = new LinkedList<>(); - users.add(user); - users.add(user2); - return users; - } - - @Override - public String userName(Long userId) { - return "User1"; - } - - @Override - public Map userMap(Long userId, User user) { - - User user2 = new User(); - user2.setUserId(2L); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - return Collections.singletonMap(2L, user2); - } - - @Override - public User userExp(Long userId) { - if (userId > 1000) { - throw new StackOverflowError(); - } - - if (userId > 100) { - throw new NullPointerException(); - } - - if (userId > 10) { - throw new RuntimeException("Exception Occur"); - } - - return getUser(userId); - - } -} diff --git a/examples/spring-boot-examples/springboot-demo-provider/src/main/resources/application.yml b/examples/spring-boot-examples/springboot-demo-provider/src/main/resources/application.yml deleted file mode 100644 index 1a645586..00000000 --- a/examples/spring-boot-examples/springboot-demo-provider/src/main/resources/application.yml +++ /dev/null @@ -1,5 +0,0 @@ -## starlight 配置 -starlight: - server: - enable: true - port: 8777 \ No newline at end of file diff --git a/examples/spring-cloud-examples/pom.xml b/examples/spring-cloud-examples/pom.xml deleted file mode 100644 index cdb6bb62..00000000 --- a/examples/spring-cloud-examples/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.0.7.RELEASE - - - - - com.baidu.cloud - spring-cloud-examples - 0.1.0-SNAPSHOT - pom - - - springcloud-demo-provider - springcloud-demo-consumer - - - - 1.8 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - ${java.version} - ${java.version} - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - diff --git a/examples/spring-cloud-examples/springcloud-demo-consumer/pom.xml b/examples/spring-cloud-examples/springcloud-demo-consumer/pom.xml deleted file mode 100644 index 45d5019e..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-consumer/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - spring-cloud-examples - 0.1.0-SNAPSHOT - - - springcloud-demo-consumer - - - 8 - 8 - - - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - - com.baidu.cloud - spring-cloud-starter-baidu-starlight - 2022.2.0 - - - - org.springframework.cloud - spring-cloud-starter-consul-discovery - 2.0.1.RELEASE - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringCloudConsumerApp.java b/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringCloudConsumerApp.java deleted file mode 100644 index d6bb8da7..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/SpringCloudConsumerApp.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer; - -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -@StarlightScan -public class SpringCloudConsumerApp { - - public static void main(String[] args) { - SpringApplication.run(SpringCloudConsumerApp.class, args); - } -} diff --git a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java b/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java deleted file mode 100644 index 3400f46a..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/UserRestService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer.service; - -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.DeleteMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PathVariable; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PutMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestParam; - -import java.util.List; -import java.util.Map; - -/** - * Starlight Rest 风格支持 - * - * @Date 2022/9/28 21:16 - * @Created by liuruisen - */ -@RequestMapping("/user") -public interface UserRestService { - - @GetMapping - User getUser(@RequestParam("userId") Long userId); - - @PutMapping - User updateUser(@RequestBody User user); - - @DeleteMapping - void deleteUser(@RequestParam("userId") Long userId); - - @PostMapping - Long saveUser(@RequestBody User user); - - @GetMapping("/connect") - void connect(); - - @PostMapping("/multiparams") - User multiParams(@RequestParam("userId") Long userId, @RequestBody User user); - - @GetMapping("/list") - List allUsers(); - - @GetMapping("/name/{userId}") - String userName(@PathVariable("userId") Long userId); - - @PostMapping("/map") - Map userMap(@RequestParam("userId") Long userId, @RequestBody User user); - - @GetMapping("/exception") - User userExp(Long userId); -} diff --git a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java b/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java deleted file mode 100644 index 70578331..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/java/com/baidu/cloud/demo/consumer/service/impl/UserRestServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.consumer.service.impl; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.demo.consumer.service.UserRestService; -import com.baidu.cloud.starlight.springcloud.client.annotation.RpcProxy; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -import java.util.List; -import java.util.Map; - -/** - * @Date 2022/9/28 21:23 - * @Created by liuruisen - */ -@RpcService -public class UserRestServiceImpl implements UserRestService { - - /** - * 不依赖注册发现,直连方式调用 - */ - @RpcProxy(name = "springcloud-demo-provider") - private UserService userService; - - @Override - public User getUser(Long userId) { - return userService.getUser(userId); - } - - @Override - public User updateUser(User user) { - return userService.updateUser(user); - } - - @Override - public void deleteUser(Long userId) { - userService.deleteUser(userId); - } - - @Override - public Long saveUser(User user) { - return userService.saveUser(user); - } - - @Override - public void connect() { - userService.connect(); - } - - @Override - public User multiParams(Long userId, User user) { - return userService.multiParams(userId, user); - } - - @Override - public List allUsers() { - return userService.allUsers(); - } - - @Override - public String userName(Long userId) { - return userService.userName(userId); - } - - @Override - public Map userMap(Long userId, User user) { - return userService.userMap(userId, user); - } - - @Override - public User userExp(Long userId) { - return userService.userExp(userId); - } -} diff --git a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/resources/application.yml b/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/resources/application.yml deleted file mode 100644 index d2d2dfb2..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-consumer/src/main/resources/application.yml +++ /dev/null @@ -1,18 +0,0 @@ -## starlight配置信息 -starlight: - server: - enable: true - port: 8888 -# client: - # config: - # default: - # serialize-mode: pb2-java - - -spring: - application: - name: springcloud-demo-consumer - cloud: - consul: - host: localhost - port: 8500 \ No newline at end of file diff --git a/examples/spring-cloud-examples/springcloud-demo-provider/pom.xml b/examples/spring-cloud-examples/springcloud-demo-provider/pom.xml deleted file mode 100644 index 4034e183..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-provider/pom.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - spring-cloud-examples - 0.1.0-SNAPSHOT - - - springcloud-demo-provider - - - 8 - 8 - - - - - - com.baidu.cloud - demo-api - 0.1.0-SNAPSHOT - - - - com.baidu.cloud - spring-cloud-starter-baidu-starlight - 2022.2.0 - - - - org.springframework.cloud - spring-cloud-starter-consul-discovery - 2.0.1.RELEASE - - - - - - - - - true - src/main/resources - - application-local.yml - bootstrap.properties - - - - true - src/main/resources - - application-${environment}.yml - bootstrap.properties - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - - - local - - true - - - local - - - - - jarvis - - jarvis - - - - - - diff --git a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringCloudProviderApp.java b/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringCloudProviderApp.java deleted file mode 100644 index 8e76f3b2..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/SpringCloudProviderApp.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider; - -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -@StarlightScan -public class SpringCloudProviderApp { - - public static void main(String[] args) { - SpringApplication.run(SpringCloudProviderApp.class, args); - } -} diff --git a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java b/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java deleted file mode 100644 index 9b97461b..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/java/com/baidu/cloud/demo/provider/service/UserServiceImpl.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.demo.provider.service; - -import com.baidu.cloud.demo.api.UserService; -import com.baidu.cloud.demo.api.model.Address; -import com.baidu.cloud.demo.api.model.ExtInfo; -import com.baidu.cloud.demo.api.model.Gender; -import com.baidu.cloud.demo.api.model.User; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -@RpcService -public class UserServiceImpl implements UserService { - - @Override - public User getUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - user.setGender(Gender.MALE); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("Beijing"))); - return user; - } - - @Override - public User updateUser(User user) { - return user; - } - - @Override - public void deleteUser(Long userId) { - System.out.println("Delete user {" + userId + "}"); - } - - @Override - public Long saveUser(User user) { - return user.getUserId(); - } - - @Override - public void connect() { - System.out.println("Connect Success"); - } - - @Override - public User multiParams(Long userId, User user) { - if (user == null) { - user = new User(); - } - user.setUserId(userId == null ? 0L : userId); - return user; - } - - @Override - public List allUsers() { - User user = new User(); - user.setUserId(1l); - user.setUserName("u1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - user.setMap(Collections.singletonMap("key", new Address("heibei"))); - - User user2 = new User(); - user2.setUserId(2l); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - List users = new LinkedList<>(); - users.add(user); - users.add(user2); - return users; - } - - @Override - public String userName(Long userId) { - return "User1"; - } - - @Override - public Map userMap(Long userId, User user) { - - User user2 = new User(); - user2.setUserId(2L); - user2.setUserName("u2"); - user2.setBalance(1000.21d); - List tags2 = new LinkedList<>(); - tags2.add("fgh"); - tags2.add("123123"); - user2.setTags(tags2); - List extInfos2 = new LinkedList<>(); - ExtInfo extInfo2 = new ExtInfo("hobby", "learn"); - extInfos2.add(extInfo2); - user2.setExtInfos(extInfos2); - user2.setMap(Collections.singletonMap("Key1", new Address("Beijing"))); - - return Collections.singletonMap(2L, user2); - } - - @Override - public User userExp(Long userId) { - if (userId > 1000) { - throw new StackOverflowError(); - } - - if (userId > 100) { - throw new NullPointerException(); - } - - if (userId > 10) { - throw new RuntimeException("Exception Occur"); - } - - return getUser(userId); - - } -} diff --git a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/resources/application.yml b/examples/spring-cloud-examples/springcloud-demo-provider/src/main/resources/application.yml deleted file mode 100644 index e83feec2..00000000 --- a/examples/spring-cloud-examples/springcloud-demo-provider/src/main/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -## starlight 配置 -starlight: - server: - enable: true - port: 8999 -spring: - application: - name: springcloud-demo-provider - cloud: - consul: - host: localhost - port: 8500 diff --git a/local_build.sh b/local_build.sh new file mode 100644 index 00000000..c2565815 --- /dev/null +++ b/local_build.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +mvn clean install -DskipTests +mvn dependency:copy-dependencies + + diff --git a/mvnw b/mvnw new file mode 100755 index 00000000..35ff643b --- /dev/null +++ b/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 00000000..dae46d49 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..05bbaace --- /dev/null +++ b/pom.xml @@ -0,0 +1,384 @@ + + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + com.baidu + brpc-java-parent + 2.5.9 + pom + + ${project.artifactId} + http://maven.apache.org + Java implementation for BRPC + + + UTF-8 + 4.1.42.Final + 1.18.8 + + + + brpc-java-core + brpc-java-naming-zookeeper + brpc-java-naming-consul + brpc-spring + brpc-spring-boot-starter + spring-cloud-brpc + brpc-java-examples + + + + GitHub Issues + https://github.com/baidu/brpc-java/issues + + + + + baidu.com + The Brpc Java Project Contributors + ad-plt@baidu.com + http://www.baidu.com/ + + + + + scm:git:git://github.com/baidu/brpc-java.git + scm:git:git@github.com:baidu/brpc-java.git + https://github.com/baidu/brpc-java + + + + + Apache 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + Baidu, Inc. + http://www.baidu.com + + + + + release + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + + attach-javadoc + compile + + jar + + + + + none + UTF-8 + UTF-8 + UTF-8 + + + + + + + oss + https://oss.sonatype.org/content/repositories/snapshots/ + + + oss + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.6 + 1.6 + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + true + + + + package + + jar + + + + com/baidu/brpc/** + + + + + + + + com.github.os72 + protoc-jar-maven-plugin + 3.6.0.1 + + + generate-sources + generate-sources + + run + + + 2.5.0 + none + true + src/main/java + + src/main/proto + + + + + generate-test-sources + generate-test-sources + + run + + + 2.5.0 + true + none + src/test/java + + src/test/proto + + + + + + + com.baidu + jprotobuf-precompile-plugin + 1.2.15 + + + com.baidu + true + + + + compile + + precompile + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + + + + + + + com.baidu + brpc-java + ${project.version} + + + com.baidu + brpc-java-naming-zookeeper + ${project.version} + + + com.baidu + brpc-java-naming-consul + ${project.version} + + + com.baidu + brpc-spring + ${project.version} + + + io.netty + netty-all + ${netty.version} + + + com.google.protobuf + protobuf-java + 2.5.0 + + + com.ecwid.consul + consul-api + 1.3.0 + + + com.googlecode.protobuf-java-format + protobuf-java-format + 1.4 + + + com.baidu + jprotobuf + 1.11.11 + + + org.slf4j + slf4j-api + 1.7.25 + + + cglib + cglib + 3.2.5 + + + org.apache.commons + commons-lang3 + 3.5 + + + org.apache.commons + commons-collections4 + 4.1 + + + org.apache.commons + commons-pool2 + 2.4.2 + + + com.google.code.gson + gson + 2.8.5 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + org.xerial.snappy + snappy-java + 1.1.7.2 + + + org.apache.curator + curator-framework + 2.13.0 + + + org.apache.curator + curator-recipes + 2.13.0 + + + com.pszymczyk.consul + embedded-consul + 1.1.0 + test + + + org.apache.curator + curator-test + 2.13.0 + test + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.8.1 + test + + + org.apache.logging.log4j + log4j-core + 2.8.1 + test + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.23.4 + test + + + + diff --git a/resources/baidu-formatter.xml b/resources/baidu-formatter.xml deleted file mode 100644 index 29d8607d..00000000 --- a/resources/baidu-formatter.xml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/license-header b/resources/license-header deleted file mode 100644 index ea8e99f5..00000000 --- a/resources/license-header +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - \ No newline at end of file diff --git a/resources/qrcode.jpeg b/resources/qrcode.jpeg deleted file mode 100644 index fc5a5775..00000000 Binary files a/resources/qrcode.jpeg and /dev/null differ diff --git a/spring-cloud-brpc/pom.xml b/spring-cloud-brpc/pom.xml new file mode 100644 index 00000000..63debae3 --- /dev/null +++ b/spring-cloud-brpc/pom.xml @@ -0,0 +1,136 @@ + + + + 4.0.0 + + com.baidu + brpc-java-parent + 2.5.9 + + + spring-cloud-brpc + jar + ${project.artifactId} + The module for Spring extendsion + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + UTF-8 + + + org.projectlombok + lombok + ${lombok.version} + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + true + + + + package + + jar + + + + com/baidu/brpc/** + + + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.5.RELEASE + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + Greenwich.SR1 + pom + import + + + + + + + com.baidu + brpc-spring + + + + com.baidu + brpc-spring-boot-starter + ${project.version} + + + + org.springframework.cloud + spring-cloud-commons + + + + org.springframework.cloud + spring-cloud-context + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + com.netflix.eureka + eureka-client + 1.9.8 + + + + org.projectlombok + lombok + + + diff --git a/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcBootstrapConfiguration.java b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcBootstrapConfiguration.java new file mode 100644 index 00000000..7c038ae8 --- /dev/null +++ b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcBootstrapConfiguration.java @@ -0,0 +1,13 @@ +package com.baidu.brpc.spring.cloud; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BrpcBootstrapConfiguration { + + @Bean + public BrpcPropertySourceLocator brpcCustomPropertySourceLocator() { + return new BrpcPropertySourceLocator(); + } +} diff --git a/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcPropertySourceLocator.java b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcPropertySourceLocator.java new file mode 100644 index 00000000..f2c73d09 --- /dev/null +++ b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcPropertySourceLocator.java @@ -0,0 +1,22 @@ +package com.baidu.brpc.spring.cloud; + +import org.springframework.cloud.bootstrap.config.PropertySourceLocator; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.HashMap; +import java.util.Map; + +public class BrpcPropertySourceLocator implements PropertySourceLocator { + public static final String ENV_NAMING_URL_KEY = "brpc.global.naming.namingServiceUrl"; + + @Override + public PropertySource locate(Environment environment) { + Map properties = new HashMap<>(); + properties.put(ENV_NAMING_URL_KEY, + SpringCloudNamingFactory.NAMING_PREFIX + "://discovery"); + MapPropertySource propertySource = new MapPropertySource("brpc", properties); + return propertySource; + } +} diff --git a/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcServiceRegistrationAutoConfiguration.java b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcServiceRegistrationAutoConfiguration.java new file mode 100644 index 00000000..18bb00ee --- /dev/null +++ b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/BrpcServiceRegistrationAutoConfiguration.java @@ -0,0 +1,67 @@ +package com.baidu.brpc.spring.cloud; + +import com.netflix.appinfo.EurekaInstanceConfig; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration; +import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; +import org.springframework.cloud.netflix.eureka.metadata.DefaultManagementMetadataProvider; +import org.springframework.cloud.netflix.eureka.metadata.ManagementMetadataProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; +import org.springframework.core.env.ConfigurableEnvironment; + +import java.util.Map; + +@Configuration +@AutoConfigureBefore(EurekaClientAutoConfiguration.class) +public class BrpcServiceRegistrationAutoConfiguration implements PriorityOrdered { + public static final String ENV_PORT_KEY = "brpc.global.server.port"; + public static final String META_DATA_PORT_KEY = "brpcPort"; + + private ConfigurableEnvironment env; + + public BrpcServiceRegistrationAutoConfiguration(ConfigurableEnvironment env) { + this.env = env; + } + + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 1; + } + + @Bean + @ConditionalOnMissingBean + public ManagementMetadataProvider serviceManagementMetadataProvider() { + return new DefaultManagementMetadataProvider(); + } + + @Bean + @ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT) + public EurekaInstanceConfigBean eurekaInstanceConfigBean( + InetUtils inetUtils, ManagementMetadataProvider managementMetadataProvider) { + EurekaInstanceConfigBean instance = new EurekaClientAutoConfiguration(env) + .eurekaInstanceConfigBean(inetUtils, managementMetadataProvider); + + String brpcPort = env.getProperty(ENV_PORT_KEY); + if (StringUtils.isNoneBlank(brpcPort)) { + instance.getMetadataMap().put(META_DATA_PORT_KEY, brpcPort); + } + return instance; + } + + private void setupJmxPort(EurekaInstanceConfigBean instance, Integer jmxPort) { + Map metadataMap = instance.getMetadataMap(); + if (metadataMap.get("jmx.port") == null && jmxPort != null) { + metadataMap.put("jmx.port", String.valueOf(jmxPort)); + } + } + + private String getProperty(String property) { + return this.env.containsProperty(property) ? this.env.getProperty(property) : ""; + } +} diff --git a/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingFactory.java b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingFactory.java new file mode 100644 index 00000000..6ecaf7ca --- /dev/null +++ b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baidu.brpc.spring.cloud; + +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NamingServiceFactory; + +public class SpringCloudNamingFactory implements NamingServiceFactory { + public static final String NAMING_PREFIX = "springcloud"; + + @Override + public String getName() { + return NAMING_PREFIX; + } + + @Override + public NamingService createNamingService(BrpcURL url) { + return new SpringCloudNamingService(url); + } +} diff --git a/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingService.java b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingService.java new file mode 100644 index 00000000..1d5dce42 --- /dev/null +++ b/spring-cloud-brpc/src/main/java/com/baidu/brpc/spring/cloud/SpringCloudNamingService.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baidu.brpc.spring.cloud; + +import com.baidu.brpc.client.instance.ServiceInstance; +import com.baidu.brpc.naming.BrpcURL; +import com.baidu.brpc.naming.Constants; +import com.baidu.brpc.naming.NamingService; +import com.baidu.brpc.naming.NotifyListener; +import com.baidu.brpc.naming.RegisterInfo; +import com.baidu.brpc.naming.SubscribeInfo; +import com.baidu.brpc.spring.boot.autoconfigure.BrpcApplicationContextUtils; +import com.baidu.brpc.utils.CustomThreadFactory; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.cloud.client.discovery.DiscoveryClient; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Setter +@Getter +public class SpringCloudNamingService implements NamingService { + private List lastInstances = new ArrayList(); + private Timer namingServiceTimer; + private int updateInterval; + private DiscoveryClient discoveryClient; + + public SpringCloudNamingService(BrpcURL namingUrl) { + this.updateInterval = Constants.DEFAULT_INTERVAL; + namingServiceTimer = new HashedWheelTimer(new CustomThreadFactory("namingService-timer-thread")); + discoveryClient = BrpcApplicationContextUtils.getBean("discoveryClient", DiscoveryClient.class); + if (discoveryClient == null) { + throw new RuntimeException("discovery client is null"); + } + } + + @Override + public List lookup(SubscribeInfo subscribeInfo) { + List discoveryInstances + = discoveryClient.getInstances(subscribeInfo.getServiceId()); + List instances = new ArrayList(); + for (org.springframework.cloud.client.ServiceInstance discoveryInstance : discoveryInstances) { + String host = discoveryInstance.getHost(); + Integer port = Integer.valueOf(discoveryInstance.getMetadata().get( + BrpcServiceRegistrationAutoConfiguration.META_DATA_PORT_KEY)); + ServiceInstance instance = new ServiceInstance(host, port); + instances.add(instance); + } + return instances; + } + + @Override + public void subscribe(SubscribeInfo subscribeInfo, final NotifyListener listener) { + namingServiceTimer.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + try { + List currentInstances = lookup(subscribeInfo); + Collection addList = CollectionUtils.subtract( + currentInstances, lastInstances); + Collection deleteList = CollectionUtils.subtract( + lastInstances, currentInstances); + listener.notify(addList, deleteList); + lastInstances = currentInstances; + } catch (Exception ex) { + // ignore exception + } + namingServiceTimer.newTimeout(this, updateInterval, TimeUnit.MILLISECONDS); + + } + }, + updateInterval, TimeUnit.MILLISECONDS); + } + + @Override + public void unsubscribe(SubscribeInfo subscribeInfo) { + namingServiceTimer.stop(); + } + + @Override + public void register(RegisterInfo registerInfo) { + } + + @Override + public void unregister(RegisterInfo registerInfo) { + } +} diff --git a/spring-cloud-brpc/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory b/spring-cloud-brpc/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory new file mode 100644 index 00000000..d4e3ea3d --- /dev/null +++ b/spring-cloud-brpc/src/main/resources/META-INF/services/com.baidu.brpc.naming.NamingServiceFactory @@ -0,0 +1 @@ +com.baidu.brpc.spring.cloud.SpringCloudNamingFactory \ No newline at end of file diff --git a/spring-cloud-brpc/src/main/resources/META-INF/spring.factories b/spring-cloud-brpc/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..4f1cd254 --- /dev/null +++ b/spring-cloud-brpc/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.baidu.brpc.spring.cloud.BrpcServiceRegistrationAutoConfiguration + +org.springframework.cloud.bootstrap.BootstrapConfiguration=\ + com.baidu.brpc.spring.cloud.BrpcBootstrapConfiguration \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/pom.xml b/spring-cloud-starter-baidu-starlight/pom.xml deleted file mode 100644 index ca5ee238..00000000 --- a/spring-cloud-starter-baidu-starlight/pom.xml +++ /dev/null @@ -1,426 +0,0 @@ - - - 4.0.0 - - - org.springframework.cloud - spring-cloud-build - 4.0.0 - - - com.baidu.cloud - spring-cloud-starter-baidu-starlight - 2025.0.1-SNAPSHOT - - ${project.groupId}:${project.artifactId} - Spring Cloud Starlight - - - UTF-8 - 17 - 2022.0.0 - - 2.0.9 - 2025.0.1-SNAPSHOT - 2.2.5 - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - - - - - - com.github.stefanbirkner - system-rules - 1.19.0 - test - - - - com.baidu.cloud - starlight-all - ${starlight.version} - - - - - - - - org.springframework.cloud - spring-cloud-starter - - - - org.springframework.cloud - spring-cloud-commons - - - - com.baidu.cloud - starlight-all - - - - org.springframework.boot - spring-boot-configuration-processor - - - - org.springframework.cloud - spring-cloud-starter-consul-discovery - true - - - - org.springframework.cloud - spring-cloud-starter-loadbalancer - - - - org.springframework.boot - spring-boot-starter-web - test - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.powermock - powermock-module-junit4 - test - - - - org.powermock - powermock-api-mockito2 - test - - - - com.github.stefanbirkner - system-rules - test - - - - com.google.code.gson - gson - 2.10.1 - - - - org.reflections - reflections - 0.10.2 - - - - org.springframework.boot - spring-boot-starter-actuator - test - - - - org.mockito - mockito-core - test - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - ${java.version} - ${java.version} - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.1 - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.4 - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.6.0 - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.2.5 - - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - org.apache.maven.plugins - maven-release-plugin - 3.0.1 - - starter-v@{project.version} - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.11.2 - - 17 - - UTF-8 - - none - - - - - - jar - - package - - -Xdoclint:none - - - - - - org.apache.maven.plugins - maven-site-plugin - 3.12.1 - - true - - - - org.jacoco - jacoco-maven-plugin - 0.8.8 - - - prepare-agent - - prepare-agent - - - - report - - report - - test - - - - - - - https://github.com/baidu/starlight - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - CPD Infra Team - cpd_inf@baidu.com - Baidu - http://www2.baidu.com - - - - scm:git:${project.scm.url} - scm:git:${project.scm.url} - https://github.com/baidu/starlight.git - HEAD - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - - - deploy - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.1.0 - - - --pinentry-mode - loopback - - - - - sign-artifacts - - sign - - verify - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.14 - true - - ossrh - https://oss.sonatype.org/ - false - - - - - - - - diff --git a/spring-cloud-starter-baidu-starlight/resources/baidu-formatter.xml b/spring-cloud-starter-baidu-starlight/resources/baidu-formatter.xml deleted file mode 100644 index 29d8607d..00000000 --- a/spring-cloud-starter-baidu-starlight/resources/baidu-formatter.xml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/resources/license-header b/spring-cloud-starter-baidu-starlight/resources/license-header deleted file mode 100644 index ea8e99f5..00000000 --- a/spring-cloud-starter-baidu-starlight/resources/license-header +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyAnnotationBeanPostProcessor.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyAnnotationBeanPostProcessor.java deleted file mode 100644 index fdbca5c0..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyAnnotationBeanPostProcessor.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.utils.EnvUtils; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.annotation.RpcProxy; -import com.baidu.cloud.starlight.springcloud.client.cluster.FailFastClusterClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.FailOverClusterClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.configuration.Configuration; -import com.baidu.cloud.thirdparty.apache.commons.lang3.reflect.FieldUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.context.EnvironmentAware; -import org.springframework.core.Ordered; -import org.springframework.core.PriorityOrdered; -import org.springframework.core.env.Environment; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.util.List; -import java.util.Map; - -/** - * Created by liuruisen on 2019-06-26. TODO 研究AOT的逻辑,继承BeanRegistrationAotProcessor实现AOT逻辑 - - * postProcessMergedBeanDefinition + postProcessProperties + findInjectionMetadata 参考 @autowire - */ -public class RpcProxyAnnotationBeanPostProcessor - implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware, EnvironmentAware, PriorityOrdered { - - public static final String BEAN_NAME = "rpcClientAnnotationBeanPostProcessor"; - - private static final String CLIENT_BEAN_NAME_SUFFIX = ".StarlightClient"; - - /** - * Bean name prefix for target beans behind scoped proxies. Used to exclude those targets from handler method - * detection, in favor of the corresponding proxies. - *

- * see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping - */ - private static final String TARGET_NAME_PREFIX = "scopedTarget."; - - private static final Logger LOGGER = LoggerFactory.getLogger(RpcProxyAnnotationBeanPostProcessor.class); - - private DefaultListableBeanFactory beanFactory; - - private PropertySourcesPlaceholdersResolver placeholdersResolver; - - @Override - public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) - throws BeansException { - Class clazz = bean.getClass(); - List fields = FieldUtils.getAllFieldsList(clazz); - if (fields != null && fields.size() > 0) { - for (Field field : fields) { - RpcProxy rpcProxy = field.getAnnotation(RpcProxy.class); - if (rpcProxy != null) { - RpcProxyInfo rpcProxyInfo = resolveRpcProxy(rpcProxy); // get and set real @RpcProxy#name value - try { - Object proxyBean = buildRpcProxyBean(field.getType(), rpcProxyInfo); - ReflectionUtils.makeAccessible(field); - field.set(bean, proxyBean); - } catch (Exception e) { - throw new BeanCreationException(beanName, e); - } - } - } - } - return pvs; - } - - /** - * Resolve rpcProxy to get the real name - * - * @param rpcProxy - * @return - */ - private RpcProxyInfo resolveRpcProxy(RpcProxy rpcProxy) { - String name = rpcProxy.name(); - if (!StringUtils.hasText(name)) { - return new RpcProxyInfo(rpcProxy, name); - } - - String realName = (String) placeholdersResolver.resolvePlaceholders(name); - if (!StringUtils.hasText(realName)) { - throw new IllegalArgumentException( - "Resolve name value of @RpcProxy#name failed, " + "the value must not be null"); - } - - return new RpcProxyInfo(rpcProxy, realName); - } - - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE - 5; // 保证本BeanPostProcessor在Autowire PostProcessor之前执行 - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - if (beanFactory instanceof ConfigurableListableBeanFactory) { - this.beanFactory = (DefaultListableBeanFactory) beanFactory; - } else { - throw new IllegalArgumentException( - "RpcProxyAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory"); - } - } - - @Override - public void setEnvironment(Environment environment) { - this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(environment); - } - - private Object buildRpcProxyBean(Class rpcProxyClass, RpcProxyInfo rpcProxyInfo) throws Exception { - // get from spring ioc (cache) - try { - String proxyBeanName = "&" + proxyBeanName(rpcProxyInfo, rpcProxyClass); - RpcProxyFactoryBean proxyBean = beanFactory.getBean(proxyBeanName, RpcProxyFactoryBean.class); - if (proxyBean != null) { - return proxyBean.getObject(); - } - } catch (NoSuchBeanDefinitionException ex) { - LOGGER.info("Get Bean {} form BeanFactory failed, will create", ex.getBeanName()); - } - - return rpcProxyBean(rpcProxyClass, rpcProxyInfo); - } - - /** - * Register {@link RpcProxyFactoryBean} and get proxy object - * - * @param proxyType - * @param rpcProxyInfo - * @return - * @throws Exception - */ - private Object rpcProxyBean(Class proxyType, RpcProxyInfo rpcProxyInfo) throws Exception { - // register or get starlight client - StarlightClient starlightClient = registerOrGetStarlightClient(rpcProxyInfo); - - // register factory bean - BeanDefinitionBuilder definitionBuilder = - BeanDefinitionBuilder.genericBeanDefinition(RpcProxyFactoryBean.class); - definitionBuilder.addPropertyValue("annotationInfos", rpcProxyInfo.getRpcProxy()); - definitionBuilder.addPropertyValue("clientName", rpcProxyInfo.getRealName()); - definitionBuilder.addPropertyValue("type", proxyType); - definitionBuilder.addPropertyValue("client", starlightClient); - definitionBuilder.addPropertyValue("clientProperties", clientProperties()); - definitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - - AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); - - String proxyBeanName = proxyBeanName(rpcProxyInfo, proxyType); - String aliasName = proxyBeanName; - if (StringUtils.hasText(rpcProxyInfo.getRpcProxy().qualifier())) { - aliasName = rpcProxyInfo.getRpcProxy().qualifier(); - } - BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, proxyBeanName, new String[] {aliasName}); - BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanFactory); - - RpcProxyFactoryBean proxyBean = beanFactory.getBean("&" + proxyBeanName, RpcProxyFactoryBean.class); - return proxyBean.getObject(); - } - - /** - * Register StarlightClient Bean Types: Single / Cluster - * - * @param rpcProxyInfo - * @return - */ - private StarlightClient registerOrGetStarlightClient(RpcProxyInfo rpcProxyInfo) { - String clientBeanName = clientBeanName(rpcProxyInfo); - - RpcProxy rpcProxy = rpcProxyInfo.getRpcProxy(); - - if (StringUtils.hasText(rpcProxy.remoteUrl())) { - String protocol = null; - if (rpcProxy.remoteUrl().contains("://")) { - protocol = rpcProxy.remoteUrl().split("://")[0]; - } - - if (!StringUtils.hasText(rpcProxy.protocol()) && !StringUtils.hasText(protocol)) { - throw new IllegalArgumentException( - "protocol in @RpcProxy#protocol is null, " + "when specify @RpcProxy#remoteUrl"); - } - return registerOrGetSingleClient(clientBeanName, rpcProxyInfo); - } - - if (StringUtils.hasText(rpcProxyInfo.getRealName())) { - return registerOrGetClusterClient(clientBeanName, rpcProxyInfo); - } - - return null; - } - - /** - * Support direct URL request - * - * @param clientBeanName - * @param rpcProxyInfo - * @return - */ - private StarlightClient registerOrGetSingleClient(String clientBeanName, RpcProxyInfo rpcProxyInfo) { - StarlightClient starlightClient = getClientFormIocCache(clientBeanName); - if (starlightClient != null) { - return starlightClient; - } - String remoteUrl = rpcProxyInfo.getRpcProxy().remoteUrl(); - if (remoteUrl.contains("://")) { - remoteUrl = remoteUrl.split("://")[1]; - } - String[] ipAndPort = remoteUrl.split(":"); - StarlightClientProperties properties = clientProperties(); - BeanDefinitionBuilder definitionBuilder = - BeanDefinitionBuilder.genericBeanDefinition(SingleStarlightClient.class); - definitionBuilder.addConstructorArgValue(ipAndPort[0]); - definitionBuilder.addConstructorArgValue(ipAndPort[1]); - definitionBuilder.addConstructorArgValue(properties.transportConfig(remoteUrl)); - definitionBuilder.setInitMethodName("init"); - definitionBuilder.setDestroyMethodName("destroy"); - definitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - - AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); - BeanDefinitionHolder holder = - new BeanDefinitionHolder(beanDefinition, clientBeanName, new String[] {clientBeanName}); - // register - BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanFactory); - // get bean - return beanFactory.getBean(clientBeanName, StarlightClient.class); - } - - /** - * Support Cluster request - * - * @param clientBeanName - * @param rpcProxyInfo - * @return - */ - private StarlightClient registerOrGetClusterClient(String clientBeanName, RpcProxyInfo rpcProxyInfo) { - StarlightClient starlightClient = getClientFormIocCache(clientBeanName); - if (starlightClient != null) { - return starlightClient; - } - StarlightClientProperties properties = clientProperties(); - String clusterModel = clusterModel(properties, rpcProxyInfo); - - BeanDefinitionBuilder definitionBuilder = null; - switch (clusterModel) { - case "failfast": - definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(FailFastClusterClient.class); - break; - case "failover": - definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(FailOverClusterClient.class); - break; - default: - throw new IllegalStateException( - "starlight.client.config {clusterModel} is null, " + "please config it before run"); - } - LoadBalancer loadBalancer = beanFactory.getBean(LoadBalancer.class); - DiscoveryClient discoveryClient = beanFactory.getBean(DiscoveryClient.class); - SingleStarlightClientManager clientManager = beanFactory.getBean(SingleStarlightClientManager.class); - Configuration configuration = null; - try { - configuration = beanFactory.getBean(Configuration.class); - } catch (BeansException e) { - LOGGER.error("No such bean of Configuration, does not depend on gravity?", e); - } - StarlightRouteProperties routeProperties = beanFactory.getBean(StarlightRouteProperties.class); - definitionBuilder.addConstructorArgValue(rpcProxyInfo.getRealName()); - definitionBuilder.addConstructorArgValue(properties); - definitionBuilder.addConstructorArgValue(loadBalancer); - definitionBuilder.addConstructorArgValue(discoveryClient); - definitionBuilder.addConstructorArgValue(clientManager); - definitionBuilder.addConstructorArgValue(configuration); - definitionBuilder.addConstructorArgValue(routeProperties); - definitionBuilder.setInitMethodName("init"); - definitionBuilder.setDestroyMethodName("destroy"); - definitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - - AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); - BeanDefinitionHolder holder = - new BeanDefinitionHolder(beanDefinition, clientBeanName, new String[] {clientBeanName}); - BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanFactory); - - return beanFactory.getBean(clientBeanName, StarlightClient.class); - } - - private StarlightClientProperties clientProperties() { - StarlightClientProperties properties = beanFactory.getBean(StarlightClientProperties.class); - if (properties.getConfig() == null || properties.getConfig().size() == 0) { - throw new IllegalStateException("starlight.client.config is null, please config it before run"); - } - - return properties; - } - - /** - * Get Cluster model from properties - * - * @param properties - * @param rpcProxyInfo - * @return - */ - private String clusterModel(StarlightClientProperties properties, RpcProxyInfo rpcProxyInfo) { - String clusterModel = properties.getClusterModel(rpcProxyInfo.getRealName()); - if (!StringUtils.hasText(clusterModel)) { - throw new IllegalStateException( - "starlight.client.config {clusterModel} is null, " + "please config it before run"); - } - - return clusterModel; - } - - /** - * Starlight Client bean name <1> when specify remoteUrl, clientBeanName will be "remoteUrl.StarlightClient <2> - * When not specify remoteUrl but specify name, clientBeanName will be "name.StarlightClient" We create - * StarlightClient bean at addressing level - * - * @param rpcProxyInfo - * @return - */ - private String clientBeanName(RpcProxyInfo rpcProxyInfo) { - String remoteUrl = rpcProxyInfo.getRpcProxy().remoteUrl(); - if (!remoteUrl.isEmpty()) { - if (remoteUrl.contains("://")) { - remoteUrl = remoteUrl.split("://")[1]; - } - return remoteUrl + CLIENT_BEAN_NAME_SUFFIX; - } - - String name = rpcProxyInfo.getRealName(); - if (!name.isEmpty()) { - return name + CLIENT_BEAN_NAME_SUFFIX; - } - - throw new IllegalStateException( - "Either name() or remoteUrl() must be provided in @" + RpcProxy.class.getSimpleName()); - } - - /** - * Proxy bean name scopedTarget.starlightClientBeanName:{protocol}:interfaceName - * - * @param rpcProxyInfo - * @param proxyType - * @return - */ - private String proxyBeanName(RpcProxyInfo rpcProxyInfo, Class proxyType) { - StringBuilder buf = new StringBuilder(TARGET_NAME_PREFIX + clientBeanName(rpcProxyInfo) + "."); - if (StringUtils.hasText(rpcProxyInfo.getRpcProxy().protocol())) { - buf.append(rpcProxyInfo.getRpcProxy().protocol()).append("."); - } - buf.append(proxyType.getName()); - return buf.toString(); - } - - /** - * Get Bean from spring ioc first Preventing repeated injection of beans - * - * @param clientBeanName - * @return - */ - private StarlightClient getClientFormIocCache(String clientBeanName) { - StarlightClient starlightClient = null; - try { - starlightClient = beanFactory.getBean(clientBeanName, StarlightClient.class); - } catch (BeansException e) { - if (e instanceof NoSuchBeanDefinitionException) { - LOGGER.info("Get bean {" + clientBeanName + "} failed, will create."); - } else { - throw e; - } - } - return starlightClient; - } - - /** - * 去掉通过反射更改注解的属性值,改为额外的包装类 以解决jdk9模块化后java.base不暴露给unnamed module问题 - */ - private static class RpcProxyInfo { - - private RpcProxy rpcProxy; - - private String realName; - - public RpcProxyInfo(RpcProxy rpcProxy, String name) { - this.rpcProxy = rpcProxy; - this.realName = name; - } - - public RpcProxy getRpcProxy() { - return rpcProxy; - } - - public void setRpcProxy(RpcProxy rpcProxy) { - this.rpcProxy = rpcProxy; - } - - public String getRealName() { - return realName; - } - - public void setRealName(String realName) { - this.realName = realName; - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyFactoryBean.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyFactoryBean.java deleted file mode 100644 index 0c80026d..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyFactoryBean.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; -import com.baidu.cloud.starlight.api.rpc.proxy.ProxyFactory; -import com.baidu.cloud.starlight.springcloud.client.annotation.RpcProxy; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; - -/** - * RpcClientFactoryBean负责生成RpcProxy的代理Bean - *

- * Created by liuruisen on 2019-05-06. - */ -public class RpcProxyFactoryBean implements FactoryBean, InitializingBean { - - private Class type; - - private Object proxy; - - private RpcProxy annotationInfos; - - private String clientName; - - private StarlightClient client; - - private StarlightClientProperties clientProperties; - - private ServiceConfig serviceConfig; - - @Override - public Object getObject() throws Exception { - if (proxy != null) { - return proxy; - } - proxy = getProxy(); - return proxy; - } - - @Override - public Class getObjectType() { - return this.type; - } - - @Override - public void afterPropertiesSet() throws Exception { - // refer - serviceConfig = new ServiceConfig(); - serviceConfig.setProtocol(getProtocol()); - serviceConfig.setCompressType(getCompressType()); - serviceConfig.setFilters(getFilters()); - serviceConfig.setServiceId(annotationInfos.serviceId()); - serviceConfig.setInvokeTimeoutMills(getRequestTimeout()); - serviceConfig.setSerializeMode(serializeMode()); - - // get proxy - proxy = getProxy(); - } - - private T getProxy() { - ProxyFactory proxyFactory = new JDKProxyFactory(); - return (T) proxyFactory.getProxy(type, serviceConfig, client); - } - - public void setType(Class type) { - this.type = type; - } - - public void setAnnotationInfos(RpcProxy annotationInfos) { - this.annotationInfos = annotationInfos; - } - - public void setClient(StarlightClient client) { - this.client = client; - } - - public void setClientProperties(StarlightClientProperties clientProperties) { - this.clientProperties = clientProperties; - } - - private String getProtocol() { - if (!StringUtils.isEmpty(annotationInfos.protocol())) { // Highest priority - return annotationInfos.protocol(); - } - - return clientProperties.getProtocol(clientName); - } - - private String getCompressType() { - return clientProperties.getCompressType(clientName); - } - - private String getFilters() { - return clientProperties.getFilters(clientName); - } - - private Integer getRequestTimeout() { - return clientProperties.getRequestTimeoutMills(clientName, type.getName()); - } - - private String serializeMode() { - return clientProperties.getSerializeMode(clientName); - } - - public String getClientName() { - return clientName; - } - - public void setClientName(String clientName) { - this.clientName = clientName; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyProviders.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyProviders.java deleted file mode 100644 index 4c121eb1..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/RpcProxyProviders.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client; - -import com.baidu.cloud.thirdparty.jackson.core.JsonProcessingException; -import com.baidu.cloud.thirdparty.jackson.databind.ObjectMapper; - -import java.util.HashSet; -import java.util.Set; - -/** - * 初始化阶段存储本consumer的所有下游服务 不存储直连的remote url Created by liuruisen on 2021/12/5. - */ -public class RpcProxyProviders { - private final ObjectMapper objectMapper = new ObjectMapper(); - - private Set providers = new HashSet<>(); - - public Set getProviders() { - return providers; - } - - public void setProviders(Set providers) { - this.providers = providers; - } - - @Override - public String toString() { - try { - return objectMapper.writeValueAsString(this); - } catch (JsonProcessingException e) { - return ""; - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/StarlightClientAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/StarlightClientAutoConfiguration.java deleted file mode 100644 index 9be71a31..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/StarlightClientAutoConfiguration.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client; - -import com.baidu.cloud.starlight.springcloud.client.annotation.RpcProxy; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.SpringCloudLoadbalancer; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import org.reflections.Reflections; -import org.reflections.scanners.FieldAnnotationsScanner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; - -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ThreadFactory; - -/** - * Created by liuruisen on 2020/3/5. - */ -@Configuration -@ConditionalOnClass(RpcProxy.class) -@EnableConfigurationProperties(value = {StarlightClientProperties.class, StarlightRouteProperties.class}) -public class StarlightClientAutoConfiguration { - - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightClientAutoConfiguration.class); - - @Bean - @ConditionalOnMissingBean - public RpcProxyAnnotationBeanPostProcessor rpcProxyBeanPostProcessor() { - return new RpcProxyAnnotationBeanPostProcessor(); - } - - @Bean - @ConditionalOnMissingBean - public ApplicationContextUtils applicationContextUtils() { - return new ApplicationContextUtils(); - } - - @Bean(destroyMethod = "destroyAll") - @ConditionalOnMissingBean - public SingleStarlightClientManager singleStarlightClientManager() { - return SingleStarlightClientManager.getInstance(); - } - - @Bean - @ConditionalOnMissingBean - public RpcProxyProviders rpcProxyProviders(StarlightRouteProperties routeProperties) { - RpcProxyProviders proxyProviders = new RpcProxyProviders(); - long startTime = System.currentTimeMillis(); - Reflections reflections = new Reflections("com", new FieldAnnotationsScanner()); - Set fields = reflections.getFieldsAnnotatedWith(RpcProxy.class); - for (Field field : fields) { - RpcProxy rpcProxy = field.getAnnotation(RpcProxy.class); - if (!StringUtils.isEmpty(rpcProxy.name()) && StringUtils.isEmpty(rpcProxy.remoteUrl())) { - if (routeProperties.getServiceIdMap() != null - && routeProperties.getServiceIdMap().containsKey(rpcProxy.name())) { - proxyProviders.getProviders().add(routeProperties.getServiceIdMap().get(rpcProxy.name())); - } else { - proxyProviders.getProviders().add(rpcProxy.name()); - } - } - } - LOGGER.info("Scanpackage {}, Provider list size is {}, content is {}, cost {}", "com", - proxyProviders.getProviders().size(), proxyProviders, System.currentTimeMillis() - startTime); - return proxyProviders; - } - - @Bean - @ConditionalOnMissingBean - public LoadBalancer springCloudLoadBalancer(LoadBalancerClient loadBalancerClient) { - SpringCloudLoadbalancer springCloudLoadbalancer = new SpringCloudLoadbalancer(loadBalancerClient); - return springCloudLoadbalancer; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/annotation/RpcProxy.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/annotation/RpcProxy.java deleted file mode 100644 index b92dd1b8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/annotation/RpcProxy.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created by liuruisen on 2020/2/25. - */ -@Target({ElementType.TYPE, ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RpcProxy { - - /** - * Service discovery name. In spring cloud context is provider Spring Application Name. A name must be specified for - * all proxy, whether or not a url is provider. - * - * @return - */ - String name() default ""; - - /** - * A Real URL, contains of protocol IP port. Example: "protocol://ip:port". Higher priority than {@link #name()}. - * The protocol is optional, default is "brpc" - * - * @return - */ - String remoteUrl() default ""; - - /** - * Rpc protocol, default is "" will select protocol according to priority Default priority: brpc > stargate > - * springrest - * - * @return - */ - String protocol() default ""; - - /** - * Rpc Service Id Default is interface.getName() Only if protocol value is "brpc", user can specify this value. - * - * @return - */ - String serviceId() default ""; - - /** - * Used for {@link org.springframework.beans.factory.annotation.Qualifier} - * - * @return - */ - String qualifier() default ""; - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClient.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClient.java deleted file mode 100644 index a7d8f601..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClient.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.label.LabelClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.label.LabelSelectorRouter; -import com.baidu.cloud.starlight.springcloud.client.properties.OutlierConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.configuration.Configuration; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.DiscoveryClient; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.ROUTE_CONTEXT_KEY; - -/** - * Created by liuruisen on 2020/1/4. - */ -public abstract class AbstractClusterClient implements StarlightClient { - - protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); - - private final String name; // spring cloud application name: {spring.application.name} - - private final LoadBalancer loadBalancer; // Choose ServiceInstance - - private final DiscoveryClient discoveryClient; // get instance from Registry Center - - protected final StarlightClientProperties properties; - - private final SingleStarlightClientManager clientManager; - - private final Map, ServiceConfig> serviceConfigs; // concurrentHashMap - - private final TransportConfig transportConfig; - - private volatile PeerStatus peerStatus; - - private final Map netErrorRetryTimes; - - private RouterChain routerChain; - - private Configuration configuration; - - private StarlightRouteProperties routeProperties; - - private Set initedInstances = new HashSet<>(); - - /** - * 构造注入,1是符合spring 4.x之后的推荐,2是给海若构造使用 - * - * @param name - * @param properties - * @param loadBalancer - * @param discoveryClient - * @param clientManager - */ - public AbstractClusterClient(String name, StarlightClientProperties properties, LoadBalancer loadBalancer, - DiscoveryClient discoveryClient, SingleStarlightClientManager clientManager, Configuration configuration, - StarlightRouteProperties routeProperties) { - this.name = name; - this.properties = properties; - this.loadBalancer = loadBalancer; - this.discoveryClient = discoveryClient; - this.serviceConfigs = new ConcurrentHashMap<>(); - this.transportConfig = properties.transportConfig(name); - this.clientManager = clientManager; - this.configuration = configuration; - this.routeProperties = routeProperties; - this.netErrorRetryTimes = new ConcurrentHashMap<>(); - } - - public String getName() { - return name; - } - - @Override - public void init() { - LOGGER.info("Init starlight client {}", getName()); - if (properties.getWarmUpEnabled(getName())) { - LOGGER.info("Warm up starlight client {}", getName()); - List instances = discoveryClient.getInstances(name); - if (instances != null && instances.size() > 0) { // preloading - int warmUpCount = warmUpSize(instances.size()); - for (int i = 0; i < warmUpCount; i++) { - try { - ServiceInstance serviceInstance = instances.get(i); - initSingleClient(serviceInstance.getHost(), serviceInstance.getPort()); - initedInstances.add(serviceInstance); - } catch (Exception e) { - LOGGER.error("Failed to init SingleClient in ClusterClient#init() method, " - + "will retry to init in ClusterClient#request() method", e); - } - } - } - } - - LabelSelectorRouter selectorRouter = - new LabelSelectorRouter(getName(), routeProperties, properties, loadBalancer); - List routes = new ArrayList<>(); - if (routeProperties != null && routeProperties.getEnabled()) { - routes.add(selectorRouter); - } else { - LOGGER.info("Will not execute xds route because route.enabled is false"); - } - - routerChain = new RouterChain(routes, selectorRouter); - - this.peerStatus = new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis()); - } - - protected SingleStarlightClient initSingleClient(String host, Integer port) { - OutlierConfig outlierConfig = properties.getOutlierConfig(getName()); - if (outlierConfig != null) { - Map transConfigAdd = new HashMap<>(); - transConfigAdd.put(SpringCloudConstants.OUTLIER_DETECT_ENABLED_KEY, - String.valueOf(outlierConfig.getEnabled())); - transConfigAdd.put(SpringCloudConstants.OUTLIER_DETECT_INTERVAL_KEY, - String.valueOf(outlierConfig.getDetectInterval())); - transConfigAdd.put(SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM_KEY, - String.valueOf(outlierConfig.getFailurePercentMinRequest())); - transConfigAdd.put(SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY, - String.valueOf(outlierConfig.getFailurePercentThreshold())); - if (outlierConfig.getFailureCountThreshold() != null) { - transConfigAdd.put(SpringCloudConstants.OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY, - String.valueOf(outlierConfig.getFailureCountThreshold())); - } - transportConfig.setAdditional(transConfigAdd); - } - - return clientManager.getOrCreateSingleClient(host, port, transportConfig); - } - - @Override - public void request(Request request, RpcCallback callback) { - callback = new NetworkErrorRetryCallback(callback); - addNetErrorRetryTimes(request); // retry when network error - addProviderAppName(request); - // sub cluster execute - boolean labelRouter = false; - Map routeContext = new HashMap<>(RpcContext.getContext().get()); - request.getNoneAdditionKv().putIfAbsent(ROUTE_CONTEXT_KEY, routeContext); - // 支持海若请求级的label selector选择, 用完删除防止向下传递 - RpcContext.getContext().remove(SpringCloudConstants.REQUEST_LABEL_SELECTOR_ROUTE_KEY); - try { - // route - LOGGER.debug("Request route_context is {}", request.getNoneAdditionKv()); - Cluster cluster = routerChain.route(request); - if (cluster.getClusterSelector() instanceof LabelClusterSelector) { - labelRouter = true; - } - // 此处set由volatile保证可见性,应不涉及线程并发问题 - cluster.setServiceRefers(serviceConfigs); - cluster.execute(request, callback); - } catch (Throwable e) { - // not enable fallback, throw - if (routeProperties.getNoInstanceFallBack() == null || !routeProperties.getNoInstanceFallBack()) { - LOGGER.error("Request failed and cannot fallback, req:{}#{}, caused by", request.getServiceName(), - request.getMethodName(), e); - throw e; - } - // fallback - if (e instanceof StarlightRpcException - && SpringCloudConstants.NO_INSTANCE_ERROR_CODE.equals(((StarlightRpcException) e).getCode()) - && !labelRouter) { - LOGGER.info("No instance found from the routed cluster, fallback to the label selector route"); - Cluster cluster = routerChain.noneRoute(request); - // 此处set由volatile保证可见性,应不涉及线程并发问题 - cluster.setServiceRefers(serviceConfigs); - cluster.execute(request, callback); - } else { - LOGGER.error("Request failed, req:{}#{}, caused by", request.getServiceName(), request.getMethodName(), - e); - throw e; - } - } - } - - // generate ClientInvoker for all Instances(Ip + port) - @Override - public void refer(Class serviceClass, ServiceConfig serviceConfig) { - if (serviceConfigs.get(serviceClass) == null) { - LOGGER.info("Refer service class {}", serviceClass.getName()); - serviceConfigs.put(serviceClass, serviceConfig); - for (ServiceInstance instance : initedInstances) { - SingleStarlightClient client = clientManager.getSingleClient(instance.getHost(), instance.getPort()); - if (client != null) { - client.refer(serviceClass, serviceConfig); - } - } - } - } - - @Override - public void destroy() { - if (serviceConfigs != null && serviceConfigs.size() > 0) { - serviceConfigs.clear(); - } - } - - private int warmUpSize(Integer instanceSize) { - Integer warmUpRatio = properties.getWarmUpRatio(getName()); - Integer warmUpCount = properties.getWarmUpCount(getName()); - - if (warmUpCount != null) { - return warmUpCount; - } - - if (warmUpRatio != null) { - return instanceSize * warmUpRatio / 100; - } - - return instanceSize; - } - - private void addNetErrorRetryTimes(Request request) { - netErrorRetryTimes.putIfAbsent(request, new AtomicInteger(properties.getNetworkErrorRetryTimes(getName()))); - } - - private void removeNetErrorRetryTimes(Request request) { - netErrorRetryTimes.remove(request); - } - - private void addProviderAppName(Request request) { - if (request.getAttachmentKv() == null) { - request.setAttachmentKv(new HashMap<>()); - } - // used in rate limiter filter - request.getAttachmentKv().put(Constants.PROVIDER_APP_NAME_KEY, getName()); - try { - // used for logging - request.getAttachmentKv().put(Constants.CONSUMER_APP_NAME_KEY, - ApplicationContextUtils.getApplicationName()); - } catch (Exception e) { - LOGGER.warn("Get appName failed, do not need to pay attention, appName will be used for logging. msg {}", - e.getMessage()); - } - } - - @Override - public boolean isActive() { - for (Map.Entry entry : clientManager.allSingleClients().entrySet()) { - if (entry.getValue().isActive()) { - return true; - } - } - return false; - } - - @Override - public PeerStatus getStatus() { - return this.peerStatus; - } - - @Override - public void updateStatus(PeerStatus newStatus) { - throw new RuntimeException("ClusterStarlightClient not support update status"); - } - - @Override - public URI remoteURI() { - throw new UnsupportedOperationException("Get remoteURI is not support in AbstractClusterClient"); - } - - private class NetworkErrorRetryCallback implements RpcCallback { - - private final RpcCallback chainedCallback; - - public NetworkErrorRetryCallback(RpcCallback callback) { - chainedCallback = callback; - } - - @Override - public void addTimeout(Timeout timeout) { - chainedCallback.addTimeout(timeout); - } - - @Override - public Request getRequest() { - return chainedCallback.getRequest(); - } - - @Override - public void onResponse(Response response) { - removeNetErrorRetryTimes(getRequest()); - chainedCallback.onResponse(response); - } - - @Override - public void onError(Throwable e) { - if (e instanceof TransportException && netErrorRetryTimes.get(getRequest()) == null) { - LOGGER.warn( - "Request to {} failed caused by network error {}, configured retryTimes {}, " - + "reqId {}, mapSize {}", - getRequest().getRemoteURI().getAddress(), ((TransportException) e).getCode(), - netErrorRetryTimes.get(getRequest()), getRequest().getId(), netErrorRetryTimes.size()); - } - if (e instanceof TransportException && netErrorRetryTimes.get(getRequest()) != null) { - int retryTimes = netErrorRetryTimes.get(getRequest()).getAndDecrement(); - if (retryTimes > 0) { - LOGGER.info("Request to {} failed because network error will retry {}", - getRequest().getRemoteURI().getAddress(), retryTimes); - request(getRequest(), chainedCallback); // retry - } else { - removeNetErrorRetryTimes(getRequest()); - chainedCallback.onError(e); - } - } else { - removeNetErrorRetryTimes(getRequest()); - chainedCallback.onError(e); - } - } - - @Override - public void addRpcChannel(RpcChannel rpcChannel) { - chainedCallback.addRpcChannel(rpcChannel); - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Cluster.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Cluster.java deleted file mode 100644 index 773db2ca..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Cluster.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; - -import java.util.Map; - -/** - * Cluster and subset cluster manager 管理集群的相关行为,如集群lb策略、outlier、超时 Created by liuruisen on 2021/9/6. - */ -public interface Cluster { - - /** - * Cluster具有执行业务请求的定位,其管控的StarlightClient应refer 服务接口 - * - * @param referServices - */ - void setServiceRefers(Map, ServiceConfig> referServices); - - /** - * Dynamically update cluster's config NOTE: must be thread safe - */ - default void updateConfig(Object clusterConfig) { - // TODO 开放集群管理能力后支持 - throw new UnsupportedOperationException("Update config is not support currently"); - } - - /** - * Every cluster holds one {@link LoadBalancer} - * - * @return - */ - LoadBalancer getLoadBalancer(); - - /** - * Metadata of the cluster - * - * @return - */ - ClusterSelector getClusterSelector(); - - /** - * Executing requests in sub-clusters, the sub-cluster can execute its own special logic, such as outlier - * - * @param request - * @param callback - */ - void execute(Request request, RpcCallback callback); -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/ClusterSelector.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/ClusterSelector.java deleted file mode 100644 index b7065590..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/ClusterSelector.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Metadata and config of the cluster Can selector instance of this cluster Created by liuruisen on 2021/9/6. - */ -public abstract class ClusterSelector { - - /** - * serviceId of the cluster(app name of provider) - */ - private String serviceId; - - /** - * the cluster name or key - */ - private String clusterName; - - /** - * 集群标识key-value对 - */ - private Map meta = new HashMap<>(); - - /** - * 筛选本集群服务列表 - * - * @param originList - * @return - */ - public abstract List selectorClusterInstances(List originList); - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public String getServiceId() { - return serviceId; - } - - public void setServiceId(String serviceId) { - this.serviceId = serviceId; - } - - public Map getMeta() { - return meta; - } - - public void setMeta(Map meta) { - this.meta = meta; - } - - protected Map getServerMeta(ServiceInstance server) { - Map meta = new HashMap<>(server.getMetadata()); - if (!meta.containsKey(SpringCloudConstants.EM_PRODUCT_LINE)) { // 真对BNS的兼容 - meta.put(SpringCloudConstants.EM_PRODUCT_LINE, getMeta().get(SpringCloudConstants.EM_PRODUCT_LINE)); - meta.put(SpringCloudConstants.EM_APP, getMeta().get(SpringCloudConstants.EM_APP)); - } - - return meta; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ClusterMeta{"); - sb.append("serviceId='").append(serviceId).append('\''); - sb.append(", clusterName='").append(clusterName).append('\''); - sb.append(", meta=").append(meta); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClient.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClient.java deleted file mode 100644 index 2f2766c7..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClient.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.configuration.Configuration; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; - -/** - * FailFastClusterClient SPI name: "failfast" Created by liuruisen on 2020/2/27. - */ -public class FailFastClusterClient extends AbstractClusterClient { - - public FailFastClusterClient(String name, StarlightClientProperties properties, LoadBalancer loadBalancer, - DiscoveryClient discoveryClient, SingleStarlightClientManager clientManager, Configuration configuration, - StarlightRouteProperties routeProperties) { - super(name, properties, loadBalancer, discoveryClient, clientManager, configuration, routeProperties); - } - - @Override - public void request(Request request, RpcCallback callback) { - super.request(request, new FailFastClusterCallback(callback)); - } - - protected class FailFastClusterCallback implements RpcCallback { - private final RpcCallback chainedCallback; - - public FailFastClusterCallback(RpcCallback callback) { - chainedCallback = callback; - } - - @Override - public void addTimeout(Timeout timeout) { - chainedCallback.addTimeout(timeout); - } - - @Override - public Request getRequest() { - return chainedCallback.getRequest(); - } - - @Override - public void onResponse(Response response) { - chainedCallback.onResponse(response); - } - - @Override - public void onError(Throwable e) { - chainedCallback.onError(e); - } - - @Override - public void addRpcChannel(RpcChannel rpcChannel) { - chainedCallback.addRpcChannel(rpcChannel); - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClient.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClient.java deleted file mode 100644 index 08115778..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClient.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.exception.RpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.configuration.Configuration; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.springframework.cloud.client.discovery.DiscoveryClient; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * FailOverClusterClient: when request failed, will retry another instance Created by liuruisen on 2020/9/21. - */ -public class FailOverClusterClient extends AbstractClusterClient { - - /** - * Key 为 Request的原因是 调用satrgate时会更改requestId - */ - private final Map remainedRetries = new ConcurrentHashMap<>(); - - private final Map retryTimesMap = new ConcurrentHashMap<>(); - - public FailOverClusterClient(String name, StarlightClientProperties properties, LoadBalancer loadBalancer, - DiscoveryClient discoveryClient, SingleStarlightClientManager clientManager, Configuration configuration, - StarlightRouteProperties routeProperties) { - super(name, properties, loadBalancer, discoveryClient, clientManager, configuration, routeProperties); - } - - @Override - public void request(Request request, RpcCallback callback) { - Integer retryTimes = retryTimes(request); - if (retryTimes == null || retryTimes <= 0) { - retryTimes = 0; - } - remainedRetries.putIfAbsent(request, new AtomicInteger(retryTimes)); // putIfAbsent - retryTimesMap.putIfAbsent(request, retryTimes); // putIfAbsent - super.request(request, new FailOverClusterCallback(callback)); - } - - /** - * Get retryTimes from properties - * - * @return - */ - private Integer retryTimes(Request request) { - return properties.getRetryTimes(getName(), request.getServiceClass().getName()); - } - - /** - * Determined whether method is retryable - * - * @return - */ - private boolean isRetryable(Request request) { - String retryableMethods = properties.getRetryMethods(getName(), request.getServiceClass().getName()); - - if (StringUtils.isEmpty(retryableMethods)) { - return false; - } - - String[] retryableMethodList = retryableMethods.split(SpringCloudConstants.RETRYABLE_SPLIT_KEY); - for (String method : retryableMethodList) { - if (request.getMethodName().startsWith(method)) { - return true; - } - } - - return false; - } - - private boolean isRetryable(RpcException rpcException, Request request) { - - String retryErrorCodes = properties.getRetryErrorCodes(getName(), request.getServiceClass().getName()); - if (StringUtils.isEmpty(retryErrorCodes)) { - return false; - } - - Integer code = rpcException.getCode(); - if (code == null) { - return false; - } - - String strCode = String.valueOf(code); - String[] retryableCodeList = retryErrorCodes.split(SpringCloudConstants.RETRYABLE_SPLIT_KEY); - for (String errCode : retryableCodeList) { - if (strCode.equals(errCode)) { - return true; - } - } - - return false; - } - - /** - * Get retry Delay timeunit mills from properties - * - * @param request - * @return - */ - private Integer retryDelayTimeUnitMills(Request request) { - return properties.getRetryDelayTimeUnitMills(getName(), request.getServiceClass().getName()); - } - - private void clearRetryTimesCache(Request request) { - retryTimesMap.remove(request); - remainedRetries.remove(request); - } - - protected class FailOverClusterCallback implements RpcCallback { - - private final RpcCallback chainedCallback; - - public FailOverClusterCallback(RpcCallback callback) { - chainedCallback = callback; - } - - @Override - public void addTimeout(Timeout timeout) { - chainedCallback.addTimeout(timeout); - } - - @Override - public Request getRequest() { - return chainedCallback.getRequest(); - } - - @Override - public void onResponse(Response response) { - Integer canRetryTimes = retryTimesMap.get(getRequest()); - AtomicInteger remindRetryTimes = remainedRetries.get(getRequest()); - if (canRetryTimes != null && remindRetryTimes != null && !canRetryTimes.equals(remindRetryTimes.get())) { // 代表经历过retry了,记录重试成功日志 - LOGGER.info( - "[FailOver] Request retry success:" + " serviceName {}, methodName {}, traceId {}, retryCount {}", - getRequest().getServiceName(), getRequest().getMethodName(), - LogUtils.parseTraceIdSpanId(getRequest()).get(LogUtils.TCID), - (canRetryTimes - remindRetryTimes.get())); - } - clearRetryTimesCache(getRequest()); - chainedCallback.onResponse(response); - } - - @Override - public void onError(Throwable e) { - Request request = getRequest(); - - if (!(e instanceof RpcException)) { - clearRetryTimesCache(request); - chainedCallback.onError(e); - } - - RpcException rpcException = (RpcException) e; - - // 1. error code can retry, retry - if (!isRetryable(rpcException, request)) { - clearRetryTimesCache(request); - chainedCallback.onError(e); - return; - } - - // 2. Method is configured to be retryable, retry - if (!isRetryable(request)) { - clearRetryTimesCache(getRequest()); - chainedCallback.onError(e); - return; - } - - // 3. reach max retry times, end the request and return exception - AtomicInteger remindRetryTimes = remainedRetries.get(request); - // There are no more retries, end the request - if (remindRetryTimes == null || remindRetryTimes.get() <= 0) { - LOGGER.warn( - "[FailOver] Request failed will not retry, reach the max retry times: " - + "serviceName {}, methodName{}, traceId {}", - request.getServiceName(), request.getMethodName(), - LogUtils.parseTraceIdSpanId(request).get(LogUtils.TCID)); - clearRetryTimesCache(request); - chainedCallback.onError(e); - return; - } - - LOGGER.warn( - "[FailOver] Request failed will retry: " - + "errorCode {}, serviceName {}, methodName {}, traceId {}, retryNo {}, exception {}. ", - rpcException.getCode(), request.getServiceName(), request.getMethodName(), - LogUtils.parseTraceIdSpanId(request).get(LogUtils.TCID), remindRetryTimes.get(), e.getMessage()); - LOGGER.debug("[FailOver] Request failed will retry, retryNo {}, route_context: {}", remindRetryTimes.get(), - request.getNoneAdditionKv().get(SpringCloudConstants.ROUTE_CONTEXT_KEY)); - - try { - int retryDelayInterval = - retryDelayTimeUnitMills(request) * (retryTimesMap.get(request) - remindRetryTimes.get()); - TimeUnit.MILLISECONDS.sleep(retryDelayInterval); - } catch (InterruptedException interruptedException) { - LOGGER.error("The delay between two retries was interrupted, this should not happen", - interruptedException); - } - - remindRetryTimes.decrementAndGet(); // decrement retry times - - request(getRequest(), chainedCallback); // retry - } - - @Override - public void addRpcChannel(RpcChannel rpcChannel) { - chainedCallback.addRpcChannel(rpcChannel); - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/LoadBalancer.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/LoadBalancer.java deleted file mode 100644 index 21c7a5ab..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/LoadBalancer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import org.springframework.cloud.client.ServiceInstance; - -/** - * Starlight LoadBalancer interface 实现类可为Ribbon,也可为springcloudloadbalancer,或者统一为springcloudLoadBalancer Created by - * liuruisen on 2021/9/6. - */ -public interface LoadBalancer { - - /** - * Choose service instance - * - * @param clusterSelector - * @return - */ - ServiceInstance choose(ClusterSelector clusterSelector); - - /** - * Choose service instance and execute request - * 重要原因是为兼容SpringCloud的LoadbalancerClient的execute方法,其execute方法中会含各种执行逻辑如Ribbon的统计信息 可按照需求考虑不兼容: 原因与替换方案 - * Ribbon执行逻辑为统计请求信息,存储RibbonContext;SpringCloudLoadBalancer为在执行前后切面; - * Ribbon的统计信息使用starlight自研方式;springcloudloadbalancer切面能力可使用或定制集群级filter - * - * @param clusterSelector - * @param instance - * @param request - * @param callback - */ - void execute(ClusterSelector clusterSelector, SingleStarlightClient starlightClient, ServiceInstance instance, - Request request, RpcCallback callback); - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Router.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Router.java deleted file mode 100644 index 8b518c1b..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/Router.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; - -/** - * - * Created by liuruisen on 2021/9/6. - */ -public interface Router extends Comparable { - - /** - * Route and return subset cluster - * - * @param request - * @return subset cluster - */ - Cluster route(Request request); - - /** - * 每个Router绑定一个serviceId,或者是元信息? - * - * @return - */ - default String getServiceId() { - return null; - } - - /** - * 获取路由用的serviceId,用于支持跨注册中心路由场景 - * - * @return - */ - String getRouteServiceId(); - - /** - * 路由优先级,从高优先级到低优先级匹配,匹配到一个Router后返回 - * - * @return - */ - int getPriority(); -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/RouterChain.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/RouterChain.java deleted file mode 100644 index 99546e74..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/RouterChain.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.springcloud.common.RouteUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; - -/** - * Created by liuruisen on 2021/9/29. - */ -public class RouterChain { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterChain.class); - - private List routers; - - private Router noneRouter; - - public RouterChain(List routers, Router noneRouter) { - if (routers != null && routers.size() > 1) { - Collections.sort(routers); - } - this.routers = routers; - this.noneRouter = noneRouter; - } - - /** - * 具有兜底的机制 - * - * @param requestContext - * @return - */ - public Cluster route(Request requestContext) { - if (routers == null || routers.size() == 0) { - return noneRoute(requestContext); - } - - for (Router router : routers) { - Cluster cluster = router.route(requestContext); - if (cluster != null) { - return cluster; - } - } - return noneRoute(requestContext); - } - - /** - * 降级路由执行逻辑, 一定能match到Cluster - * - * @param requestContext - * @return - */ - public Cluster noneRoute(Request request) { - LOGGER.info("[NONE_ROUTE] Request matched none route: req {}, routeClass {}", RouteUtils.reqMsg(request), - noneRouter.getClass().getSimpleName()); - return noneRouter.route(request); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManager.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManager.java deleted file mode 100644 index d3c05ae8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManager.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadFactory; - -/** - * Through this class, you can obtain and manage all the StarlightClient during the runtime. Singleton, can be used any - * time the program is running Created by liuruisen on 2020/12/1. - */ -public class SingleStarlightClientManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(SingleStarlightClientManager.class); - - /** - * The latest SingleStarlightClient - */ - private final Map starlightClients; - private static SingleStarlightClientManager clientManager; - - private ThreadFactory ioThreadFactory; - - public SingleStarlightClientManager() { - this.starlightClients = new ConcurrentHashMap<>(); - } - - /** - * Singleton instance - * - * @return - */ - public static SingleStarlightClientManager getInstance() { - if (clientManager == null) { - synchronized (SingleStarlightClientManager.class) { - if (clientManager == null) { - clientManager = new SingleStarlightClientManager(); - } - } - } - return clientManager; - } - - /** - * Get or create SingleStarlightClient Thread-safe - * - * @param host - * @param port - * @param config - * @return - */ - public SingleStarlightClient getOrCreateSingleClient(String host, Integer port, TransportConfig config, - Map, ServiceConfig> serviceConfigs) { - SingleStarlightClient client = getAliveSingleClient(host, port); - if (client != null) { - if (serviceConfigs != null && serviceConfigs.size() > 0) { - for (Map.Entry, ServiceConfig> entry : serviceConfigs.entrySet()) { - client.refer(entry.getKey(), entry.getValue()); - } - } - return client; - } - - synchronized (this) { - client = getAliveSingleClient(host, port); - if (client != null) { - return client; - } - client = createSingleClient(host, port, config); - if (serviceConfigs != null && serviceConfigs.size() > 0) { - for (Map.Entry, ServiceConfig> entry : serviceConfigs.entrySet()) { - client.refer(entry.getKey(), entry.getValue()); - } - } - // put into manager, or update - String clientId = InstanceUtils.ipPortStr(host, port); - starlightClients.put(clientId, client); - } - - return client; - } - - public SingleStarlightClient getOrCreateSingleClient(String host, Integer port, TransportConfig config) { - return getOrCreateSingleClient(host, port, config, null); - } - - protected SingleStarlightClient createSingleClient(String host, Integer port, TransportConfig config) { - // init - SingleStarlightClient singleClient = new SingleStarlightClient(host, port, config, ioThreadFactory); - singleClient.init(); - - return singleClient; - } - - public SingleStarlightClient getSingleClient(String host, Integer port) { - return starlightClients.get(InstanceUtils.ipPortStr(host, port)); - } - - public SingleStarlightClient getAliveSingleClient(String host, Integer port) { - SingleStarlightClient client = getSingleClient(host, port); - - if (client == null) { - return null; - } - - if (client.isActive()) { - return client; - } - - // 异常实例摘除场景达到最大摘除阈值后,也可返回OUTLIER的实例 - if (client.getStatus() != null && PeerStatus.Status.OUTLIER.equals(client.getStatus().getStatus())) { - return client; - } - - return null; - } - - /** - * Remove offline client, used in clean up Task - * - * @param host - * @param port - */ - public void removeSingleClient(String host, Integer port) { - SingleStarlightClient client = starlightClients.remove(InstanceUtils.ipPortStr(host, port)); - if (client != null) { - LOGGER.info("Remove and destroy inactive SingleStarlightClient from StarlightClientManager, " - + "host {}, port {}, isActive {}", host, port, client.isActive()); - client.destroy(); // gracefully or not - } - } - - public Map allSingleClients() { - return this.starlightClients; - } - - /** - * Destroy all SingleStarlightClients, gracefully shutdown - */ - public void destroyAll() { - for (Map.Entry entry : starlightClients.entrySet()) { - entry.getValue().destroy(); - } - - starlightClients.clear(); - } - - public void setIoThreadFactory(ThreadFactory ioThreadFactory) { - this.ioThreadFactory = ioThreadFactory; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequest.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequest.java deleted file mode 100644 index 50b2238a..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; - -/** - * Created by liuruisen on 2020/1/4. - */ -public class StarlightLBRequest implements LoadBalancerRequest { - - private StarlightClient starlightClient; - - private Request request; - - private RpcCallback callback; - - public StarlightLBRequest(StarlightClient client, Request request, RpcCallback callback) { - this.starlightClient = client; - this.request = request; - this.callback = callback; - } - - @Override - public Response apply(ServiceInstance instance) throws Exception { - starlightClient.request(request, callback); - return null; - } - - /** - * get original rpc request - * - * @return - */ - public Request getDelegateRequest() { - return request; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/LoadbalancerNamedContextInitializer.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/LoadbalancerNamedContextInitializer.java deleted file mode 100644 index 4dbebc3f..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/LoadbalancerNamedContextInitializer.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.cloud.client.loadbalancer.LoadBalancerEagerLoadProperties; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationListener; - -import java.util.HashSet; -import java.util.Set; - -/** - * 用于预加载Loadbalancer子Context以及相应的bean,优化第一次请求的速度,相应的会造成启动时间变长 Created by liuruisen on 2021/9/27. - */ -public class LoadbalancerNamedContextInitializer - implements ApplicationListener, ApplicationContextAware { - - private static final Logger LOGGER = LoggerFactory.getLogger(LoadbalancerNamedContextInitializer.class); - - private static final String ALL_CLIENT_NAMES = "*"; - - private final LoadBalancerClientFactory factory; - - private final LoadBalancerEagerLoadProperties eagerProperties; - - public LoadbalancerNamedContextInitializer(LoadBalancerClientFactory factory, - LoadBalancerEagerLoadProperties properties) { - this.factory = factory; - this.eagerProperties = properties; - } - - @Override - public void onApplicationEvent(ApplicationStartedEvent event) { - autoInit(); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - - } - - /** - * 自动初始化Context - */ - public void autoInit() { - if (eagerProperties.getClients() == null || eagerProperties.getClients().isEmpty()) { - return; - } - try { - String clientName0 = eagerProperties.getClients().get(0); - Set serviceNames = new HashSet<>(eagerProperties.getClients()); - // all clients init: * - if (clientName0.trim().equalsIgnoreCase(ALL_CLIENT_NAMES)) { - serviceNames = factory.getContextNames(); - - } - for (String clientName : serviceNames) { - factory.getInstance(clientName); - } - } catch (Throwable e) { - LOGGER.warn("Auto initialize loadbalancer contexts failed, caused by ", e); - } - } - - /** - * 主动调用初始化context - */ - public void manualInit(String clientName) { - if (factory == null) { - LOGGER.warn("SpringClientFactory is null when manual call init, plz make sure the bean is injection"); - } - try { - LOGGER.debug("Manual initialize loadbalancer context {} initializing", clientName); - factory.getInstance(clientName); - LOGGER.debug("Manual initialize loadbalancer context {} initialized", clientName); - } catch (Throwable e) { - LOGGER.warn("Manual initialize loadbalancer context " + clientName + " failed, caused by ", e); - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStore.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStore.java deleted file mode 100644 index de9ec08d..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStore.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.util.StringUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2021/7/27. - */ -public class ServiceInstanceLocalStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInstanceLocalStore.class); - - private static final Integer STORE_LOCAL_CACHE_DELAY = 3 * 60 * 1000; - - private final String clientName; - - private final StarlightClientProperties starlightProperties; - - /** - * Local mem cache of Ribbon Server, stored in local disk - */ - private Properties localSrvListCache; - - private File cacheFile; - - private static final Gson GSON = new Gson(); - - private ScheduledExecutorService storeCacheExecutor; - - public ServiceInstanceLocalStore(String clientName, StarlightClientProperties clientProperties) { - this.clientName = clientName; - this.starlightProperties = clientProperties; - initLocalCache(); - } - - /** - * init local cache <1> create disk file <2> load from disk file and store in mem - */ - public void initLocalCache() { - // enable local cache - if (starlightProperties.getLocalCacheEnabled(clientName)) { - localSrvListCache = new Properties(); - String cacheFilePath = getCacheFileName(); - // 非强依赖,创建不成功仍可以继续执行,只是会缺少本地文件缓存能力 - createCacheFile(cacheFilePath); - // load server list from disk, will be temporarily stored in memory(Properties) - loadCachedListOfServers(); - - // store cache executor - storeCacheExecutor = - Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("StoreLocal-" + clientName)); - storeCacheExecutor.scheduleWithFixedDelay(this::storeCachedListOfServer, STORE_LOCAL_CACHE_DELAY, - STORE_LOCAL_CACHE_DELAY, TimeUnit.MILLISECONDS); - } - } - - /** - * Load server list from local disk - */ - public void loadCachedListOfServers() { - if (cacheFile != null && cacheFile.exists()) { - InputStream in = null; - try { - in = new FileInputStream(cacheFile); - localSrvListCache.load(in); - LOGGER.info("Load server list of " + clientName + " from local disk success"); - } catch (Throwable e) { - LOGGER.warn("Load server list of " + clientName + " from local disk failed. ", e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - LOGGER.warn("Close cache file input stream failed. ", e); - } - } - } - } - } - - /** - * Get the server list from local disk - * - * @return - */ - public List getCachedListOfServers() { - List cachedServerList = new ArrayList<>(); - - Set> cacheEntries = localSrvListCache.entrySet(); - if (cacheEntries.size() == 0) { - LOGGER.info("Local cache dose not have any server when get server list from it."); - return cachedServerList; - } - - long getStartTime = System.currentTimeMillis(); - - for (Map.Entry entry : cacheEntries) { - String serversClassName = (String) entry.getKey(); - String serverListJson = (String) entry.getValue(); - if (!StringUtils.isEmpty(serversClassName) && !StringUtils.isEmpty(serverListJson)) { - try { - List cachedList = jsonToServerList(serverListJson, Class.forName(serversClassName)); - cachedServerList.addAll(cachedList); - LOGGER.info("Get server list from local cache success, size {}", cachedServerList.size()); - break; - } catch (ClassNotFoundException e) { - LOGGER.warn("Get server list from local cache failed. ", e); - break; - } - } - } - long getCost = System.currentTimeMillis() - getStartTime; - if (getCost > 2000) { - LOGGER.info("Get cache list cost {}ms", getCost); - } - LOGGER.debug("Get cache list cost {}ms", getCost); - return cachedServerList; - } - - private List jsonToServerList(String json, Class serverClass) { - Type type = new TypeToken>() {}.getType(); - ArrayList jsonObjs = GSON.fromJson(json, type); - - List serverList = new ArrayList<>(); - for (JsonObject jsonObj : jsonObjs) { - serverList.add(GSON.fromJson(jsonObj, serverClass)); - } - - return serverList; - } - - /** - * Update the server list in mem cache. - * - * @param servers - */ - public void updateCachedListOfServers(List servers) { - if (servers == null || servers.size() == 0) { - return; - } - long updateStartTime = System.currentTimeMillis(); - - String serversClassName = servers.get(0).getClass().getName(); - String serverListJson = GSON.toJson(servers); - // update mem - localSrvListCache.setProperty(serversClassName, serverListJson); - - long updateCost = System.currentTimeMillis() - updateStartTime; - if (updateCost > 2000) { - LOGGER.info("Update CachedListOfServers cost {}ms", updateCost); - } - LOGGER.debug("Update CachedListOfServers cost {}ms", updateCost); - } - - /** - * Store server list to local disk synchronized 防止退出时更新本地文件与定时任务更新 - */ - public synchronized void storeCachedListOfServer() { - if (cacheFile == null || !cacheFile.exists()) { - return; - } - long startTime = System.currentTimeMillis(); - // notice: 当前场景 均为单线程进行文件的存储和读取,不存在并发的问题 - try { - try (FileOutputStream out = new FileOutputStream(cacheFile)) { - localSrvListCache.store(out, "Starlight Local Registry"); - } - } catch (Throwable e) { - LOGGER.warn("Store server list to local disk cache failed. ", e); - } - long storeCost = System.currentTimeMillis() - startTime; - if (storeCost > 2000) { - LOGGER.info("Store CachedListOfServers cost {}ms", storeCost); - } - LOGGER.debug("Store CachedListOfServers cost {}ms", storeCost); - } - - /** - * Close local store - */ - public void close() { - if (storeCacheExecutor != null) { - storeCacheExecutor.shutdown(); - } - - storeCachedListOfServer(); - } - - private String getCacheFileName() { - return System.getProperty("java.io.tmpdir") + "/starlight/local-registry/" + clientName + ".cache"; - } - - protected void createCacheFile(String cacheFilePath) { - cacheFile = new File(cacheFilePath); - if (!cacheFile.getParentFile().exists()) { // dir not exist create - if (!cacheFile.getParentFile().mkdirs()) { - LOGGER.warn("Invalid file cache path " + cacheFilePath + ", failed to create dirs " - + cacheFile.getParentFile()); - } else { - try { - if (!cacheFile.exists()) { - cacheFile.createNewFile(); - } - } catch (IOException e) { - LOGGER.warn("Create new cache file failed when init local cache, cause by: {}", e.getMessage()); - } - } - } else { - try { - if (!cacheFile.exists()) { - cacheFile.createNewFile(); - } - } catch (IOException e) { - LOGGER.warn("Create new cache file failed when init local cache, cause by: {}", e.getMessage()); - } - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/SpringCloudLoadbalancer.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/SpringCloudLoadbalancer.java deleted file mode 100644 index 6c85888a..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/SpringCloudLoadbalancer.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.cluster.StarlightLBRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.REQUEST_ROUTE_KEY; - -/** - * Springcloud implementation of {@link LoadBalancer}, use {@link LoadBalancerClient} to execute load balancing logic - * Created by liuruisen on 2021/9/26. - */ -public class SpringCloudLoadbalancer implements LoadBalancer { - - private static final Logger LOGGER = LoggerFactory.getLogger(SpringCloudLoadbalancer.class); - - private LoadBalancerClient loadBalancerClient; - - public SpringCloudLoadbalancer(LoadBalancerClient loadBalancerClient) { - this.loadBalancerClient = loadBalancerClient; - } - - @Override - public ServiceInstance choose(ClusterSelector clusterSelector) { - - // 路由采用的方案为: - // 通过RpcContext设置ClusterMeta信息,在StarlightLoadBalancer的choose方法中执行筛选 - // StarlightLoadBalancer举例,如ribbon的BaseLoadBalancer实现 - long chooseStart = System.currentTimeMillis(); - RpcContext.getContext().set(REQUEST_ROUTE_KEY, clusterSelector); - ServiceInstance instance = loadBalancerClient.choose(clusterSelector.getServiceId()); - RpcContext.getContext().remove(REQUEST_ROUTE_KEY); - LOGGER.debug("Spring cloud loadblancer choose instance for {} cost {}", clusterSelector.getServiceId(), - System.currentTimeMillis() - chooseStart); - return instance; - } - - @Override - public void execute(ClusterSelector clusterSelector, SingleStarlightClient starlightClient, - ServiceInstance instance, Request request, RpcCallback callback) { - try { - loadBalancerClient.execute(clusterSelector.getServiceId(), instance, - new StarlightLBRequest(starlightClient, request, callback)); - } catch (Throwable e) { - throw new StarlightRpcException("Failed to execute request in loadbalancer, " + "instance " - + instance.getHost() + ":" + instance.getPort(), e); - } - } - - /** - * TODO: 可后续可实现动态更新负载均衡算法的逻辑 LoadBalancer的Spring cloud实现更新负载均衡规则时, - * 不能直接替换LoadBalancer实现,需changeLoadBalanceRule方法在内部进行更改 注意,考虑change时的并发保护 public void changeLoadBalanceRule(String - * ruleName) { // do nothing } - */ - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightActiveServiceInstanceListSupplier.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightActiveServiceInstanceListSupplier.java deleted file mode 100644 index ebd9d9a1..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightActiveServiceInstanceListSupplier.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.Request; -import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier; -import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; -import org.springframework.context.ConfigurableApplicationContext; -import reactor.core.publisher.Flux; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -/** - * 每个下游对应一个ServiceInstanceListSupplier 在此处实现 异常实例摘除、shutdown实例摘除、路由实例筛选逻辑 - * - * @Date 2022/12/9 15:13 - * @Created by liuruisen - */ -public class StarlightActiveServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier { - - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightActiveServiceInstanceListSupplier.class); - - /** - * 30 min - */ - private static final Integer CLEAN_UP_TASK_INIT_DELAY_SECOND = 30 * 60; - - /** - * 1h - */ - private static final Integer OFFLINE_CLIENT_CLEAN_UP_PERIOD = 60 * 60; - - private StarlightClientProperties clientProperties; - - private ServiceInstanceLocalStore localStore; - - private final SingleStarlightClientManager clientManager; - - private List serverListFilters; - - private ScheduledFuture scheduledFuture; - - public StarlightActiveServiceInstanceListSupplier(ConfigurableApplicationContext context, - ServiceInstanceListSupplier delegate) { - super(delegate); - this.clientProperties = context.getBean(StarlightClientProperties.class); - this.clientManager = context.getBean(SingleStarlightClientManager.class); - Map filterMap = context.getBeansOfType(StarlightServerListFilter.class); - if (filterMap != null && !filterMap.isEmpty()) { - this.serverListFilters = filterMap.values().stream().toList(); - } else { - this.serverListFilters = new ArrayList<>(); - } - } - - @Override - public Flux> get() { - return delegate.get().map(serviceInstances -> activeServers(serviceInstances)); - } - - @Override - public Flux> get(Request request) { - return get(); - } - - @Override - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - - if (clientProperties.getLocalCacheEnabled(getServiceId())) { - localStore = new ServiceInstanceLocalStore(getServiceId(), clientProperties); - } - ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - scheduledFuture = executorService.scheduleAtFixedRate(new ClientCleanUpTask(), CLEAN_UP_TASK_INIT_DELAY_SECOND, - OFFLINE_CLIENT_CLEAN_UP_PERIOD, TimeUnit.SECONDS); - } - - @Override - public void destroy() throws Exception { - super.destroy(); - if (scheduledFuture != null && !scheduledFuture.isCancelled()) { - scheduledFuture.cancel(true); - } - - if (localStore != null) { - localStore.close(); - localStore = null; // 防止海若逻辑二次关闭 - } - - for (StarlightServerListFilter serverListFilter : serverListFilters) { - serverListFilter.destroy(); - } - } - - /** - * Get active servers - * - * @param originServers - * @return - */ - protected List activeServers(List originServers) { - - originServers = updateOrGetCacheServers(originServers); - - if (originServers == null || originServers.size() < 1) { - return originServers; - } - - if (serverListFilters == null || serverListFilters.size() < 1) { - return originServers; - } - - List serverList = new LinkedList<>(originServers); // the original servers is unmodifiable, - // copy once - for (StarlightServerListFilter serverListFilter : serverListFilters) { - serverList = serverListFilter.getFilteredList(serverList); - } - - return serverList; - } - - private List updateOrGetCacheServers(List originServers) { - - if (!clientProperties.getLocalCacheEnabled(getServiceId()) || localStore == null) { - return originServers; - } - - try { - if (originServers == null || originServers.size() == 0) { - // get servers from local cache - return localStore.getCachedListOfServers(); - } else { - // update cache - localStore.updateCachedListOfServers(originServers); - return originServers; - } - } catch (Throwable e) { - LOGGER.warn("Update or get cached servers failed, caused by ", e); - } - - return originServers; - } - - /** - * Clean up unused client - */ - private class ClientCleanUpTask implements Runnable { - @Override - public void run() { - for (Map.Entry entry : clientManager.allSingleClients().entrySet()) { - if (!entry.getValue().isActive()) { - long inactiveDuration = - System.currentTimeMillis() - entry.getValue().getStatus().getStatusRecordTime(); - if (inactiveDuration >= OFFLINE_CLIENT_CLEAN_UP_PERIOD * 1000) { - String clientId = entry.getKey(); - String[] ipPort = clientId.split(":"); - LOGGER.info("StarlightActiveLoadBalancer detects that remote {} " - + "has not been used for 2h, will remove from ClientManager", clientId); - clientManager.removeSingleClient(ipPort[0], Integer.valueOf(ipPort[1])); - for (StarlightServerListFilter filter : serverListFilters) { - if (filter.getServerListFilterTasks() == null) { - continue; - } - Object timeout = filter.getServerListFilterTasks().get(clientId); - if (timeout instanceof Timeout) { - LOGGER.info("StarlightActiveLoadBalancer detects that remote {} " - + "has not been used for 2h, will cancel the tasks", clientId); - ((Timeout) timeout).cancel(); - } - } - } - } - } - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerAutoConfiguration.java deleted file mode 100644 index 588c2866..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerAutoConfiguration.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.springcloud.client.StarlightClientAutoConfiguration; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties; -import org.springframework.cloud.client.loadbalancer.LoadBalancerEagerLoadProperties; -import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification; -import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; -import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.Collections; -import java.util.List; - -/** - * Created by liuruisen on 2020/12/3. - */ -@Configuration -@AutoConfigureBefore(value = {LoadBalancerAutoConfiguration.class}) -@AutoConfigureAfter(value = {StarlightClientAutoConfiguration.class}) -@LoadBalancerClients(defaultConfiguration = StarlightLoadbalancerConfiguration.class) -public class StarlightLoadBalancerAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties, - ObjectProvider> configurations) { - LoadBalancerClientFactory clientFactory = new StarlightLoadBalancerClientFactory(properties); - clientFactory.setConfigurations(configurations.getIfAvailable(Collections::emptyList)); - return clientFactory; - } - - @Bean - @ConditionalOnBean(LoadBalancerClientFactory.class) - @ConditionalOnMissingBean - public LoadBalancerClient weightedBlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) { - return new WeightedBlockLoadBalanceClient(loadBalancerClientFactory); - } - - @Bean - public LoadbalancerNamedContextInitializer allEagerContextInitializer(LoadBalancerClientFactory clientFactory, - LoadBalancerEagerLoadProperties properties) { - return new LoadbalancerNamedContextInitializer(clientFactory, properties); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerClientFactory.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerClientFactory.java deleted file mode 100644 index 160de7f7..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadBalancerClientFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.context.annotation.AnnotationConfigRegistry; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.util.Assert; - -public class StarlightLoadBalancerClientFactory extends LoadBalancerClientFactory { - - private static final String GRAVITY_DISCOVERY_CLIENT = - "com.baidu.cloud.gravity.discovery.discovery.GravityDiscoveryClient"; - - private static final String BNS_DISCOVERY_CLIENT = "com.baidu.cloud.bns.discovery.BnsDiscoveryClient"; - - @Autowired - private LoadBalancerClientsProperties properties; - - public StarlightLoadBalancerClientFactory(LoadBalancerClientsProperties properties) { - super(properties); - } - - @Override - public void registerBeans(String name, GenericApplicationContext context) { - - Assert.isInstanceOf(AnnotationConfigRegistry.class, context); - BeanDefinitionRegistry registry = (BeanDefinitionRegistry) context; - - if (InstanceUtils.isGravityServiceId(name)) { - // 注册gravity服务发现 - - BeanDefinitionBuilder beanDefinitionBuilder = - BeanDefinitionBuilder.genericBeanDefinition(GRAVITY_DISCOVERY_CLIENT); - GenericBeanDefinition beanDefinition = new GenericBeanDefinition(beanDefinitionBuilder.getBeanDefinition()); - beanDefinition.setPrimary(true); - - registry.registerBeanDefinition("delegate", beanDefinition); - } else if (InstanceUtils.isBnsServiceId(name)) { - // 注册bns服务发现 - BeanDefinitionBuilder beanDefinitionBuilder = - BeanDefinitionBuilder.genericBeanDefinition(BNS_DISCOVERY_CLIENT); - GenericBeanDefinition beanDefinition = new GenericBeanDefinition(beanDefinitionBuilder.getBeanDefinition()); - beanDefinition.setPrimary(true); - - registry.registerBeanDefinition("delegate", beanDefinition); - - } - - super.registerBeans(name, context); - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadbalancerConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadbalancerConfiguration.java deleted file mode 100644 index add0c302..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightLoadbalancerConfiguration.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.RoutableServerListFilter; -import com.baidu.cloud.starlight.springcloud.client.outlier.OutlierEjectServerListFilter; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.client.shutdown.ShutdownServerListFilter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; - -/** - * Created by liuruisen on 2020/12/3. - */ -@Configuration -public class StarlightLoadbalancerConfiguration { - - @Bean - @ConditionalOnMissingBean - public OutlierEjectServerListFilter outlierEjectServerListFilter(SingleStarlightClientManager clientManager, - StarlightClientProperties clientProperties, Environment environment, LoadBalancerClientFactory clientFactory) { - String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); - return new OutlierEjectServerListFilter(clientManager, clientProperties, name); - } - - @Bean - @ConditionalOnMissingBean - public ShutdownServerListFilter shutdownServerListFilter(SingleStarlightClientManager clientManager, - StarlightClientProperties clientProperties) { - return new ShutdownServerListFilter(clientManager, clientProperties); - } - - @Bean - @ConditionalOnMissingBean - public RoutableServerListFilter routableServerListFilter(Environment environment, - LoadBalancerClientFactory clientFactory, SingleStarlightClientManager clientManager, - StarlightRouteProperties routeProperties) { - String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); - return new RoutableServerListFilter(clientManager, routeProperties, name); - } - - @Bean - @ConditionalOnBean(DiscoveryClient.class) - @ConditionalOnMissingBean - public ServiceInstanceListSupplier - discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) { - return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient() - .with((context1, delegate) -> new StarlightActiveServiceInstanceListSupplier(context, delegate)) - .build(context); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightServerListFilter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightServerListFilter.java deleted file mode 100644 index 6b248229..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/StarlightServerListFilter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.thirdparty.netty.util.HashedWheelTimer; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.Timer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.core.Ordered; - -import java.util.List; -import java.util.Map; - -/** - * Ribbon service list filter defined by Starlight. Support filtering server list peer request, pay attention to the - * time-consuming execution of filters. Execute in ascending order of {@link Ordered} value. - * - * Created by liuruisen on 2021/4/22. - */ -public interface StarlightServerListFilter extends Ordered { - - Logger LOGGER = LoggerFactory.getLogger(StarlightServerListFilter.class); - - /** - * Timer used to execute recover tasks, such as clean task - */ - Timer SERVER_LIST_FILTER_TIMER = new HashedWheelTimer(new NamedThreadFactory("ServerListRecoverTimer")); - - /** - * Filter origin server list to get more stable server list. - * - * @param originList - * @return - */ - List getFilteredList(List originList); - - /** - * Server list filter timer tasks, such as clean up tasks or recover tasks - * - * @return - */ - Map getServerListFilterTasks(); - - /** - * Submit the server list filter timer task - * - * @param server - * @param execDelay - */ - void submitTimerTask(ServiceInstance server, Integer execDelay); - - /** - * Destroy - */ - void destroy(); - - /** - * FIXME 改造为ClientManagerAware的形式 - * - * @return - */ - SingleStarlightClientManager getSingleClientManager(); -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/WeightedBlockLoadBalanceClient.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/WeightedBlockLoadBalanceClient.java deleted file mode 100644 index 2d6cfe64..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/WeightedBlockLoadBalanceClient.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.Request; -import org.springframework.cloud.client.loadbalancer.Response; -import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; -import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; -import reactor.core.publisher.Mono; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.REQUEST_ROUTE_KEY; - -/** - * 配合权重路由使用的负载均衡客户端 - * - * @Date 2022/12/9 18:17 - * @Created by liuruisen - */ -public class WeightedBlockLoadBalanceClient extends BlockingLoadBalancerClient { - - private final Map> clusterRules; - - private final ReactiveLoadBalancer.Factory loadBalancerClientFactory; - - public WeightedBlockLoadBalanceClient(ReactiveLoadBalancer.Factory loadBalancerClientFactory) { - super(loadBalancerClientFactory); - this.clusterRules = new ConcurrentHashMap<>(); - this.loadBalancerClientFactory = loadBalancerClientFactory; - } - - @Override - public ServiceInstance choose(String serviceId, Request request) { - ClusterSelector clusterSelector = RpcContext.getContext().get(REQUEST_ROUTE_KEY); - if (clusterSelector == null) { - return super.choose(serviceId, request); - } - - String subClusterKey = clusterSelector.getClusterName(); - ReactiveLoadBalancer loadBalancer = clusterRules.get(subClusterKey); - if (loadBalancer == null) { - loadBalancer = loadBalancerClientFactory.getInstance(serviceId); - if (loadBalancer == null) { - return null; - } - clusterRules.put(subClusterKey, loadBalancer); - } - - Response loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block(); - if (loadBalancerResponse == null) { - return null; - } - return loadBalancerResponse.getServer(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LalbLatencyStats.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LalbLatencyStats.java deleted file mode 100644 index 5ca1eea4..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LalbLatencyStats.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.lalb; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.statistics.Stats; - -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * LALB负载均衡场景记录请求时延信息 Created by liuruisen on 2020/10/9. - */ -public class LalbLatencyStats implements Stats { - - /** - * 计算平均响应时间的窗口大小,太长对于变化感知不及时,太短准确性较低 综合考虑后,采取stargate实践验证过的数值 10 - */ - public static final Integer DEFAULT_WINDOW_SIZE = 10; - - private final Queue latencyWindow; - - public LalbLatencyStats() { - this.latencyWindow = new ConcurrentLinkedQueue<>(); - } - - public Queue getLatencyWindow() { - return latencyWindow; - } - - /** - * - * @param latency - */ - public void updateLatencyWindow(Long latency) { - Queue latencyWindow = getLatencyWindow(); - latencyWindow.add(latency); - if (latencyWindow.size() > DEFAULT_WINDOW_SIZE) { - latencyWindow.poll(); // clear excess data - } - } - - /** - * ServiceInstance avg latency - * - * @return - */ - public Long avgLatency() { - return avgLatency(latencyWindow.size()); - } - - protected Long avgLatency(int windowSize) { - if (windowSize == 0) { - return 0L; - } - Long latencies = 0L; - for (Long latency : latencyWindow) { - latencies += latency; - } - return latencies / windowSize; - } - - @Override - public void record(Request request, Response response) { - Long latency = latency(request, response); - if (latency != null) { - updateLatencyWindow(latency); - } - } - - private Long latency(Request request, Response response) { - Object latency = request.getNoneAdditionKv().get(Constants.CLIENT_REQUEST_COST); - if (latency instanceof Long) { - return (Long) latency; - } - // Impossible to happen - return null; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LocalityAwareLoadBalancer.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LocalityAwareLoadBalancer.java deleted file mode 100644 index 376e49df..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/LocalityAwareLoadBalancer.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.lalb; - -import com.baidu.cloud.starlight.api.statistics.Stats; -import com.baidu.cloud.starlight.core.statistics.StarlightStatistics; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.DefaultResponse; -import org.springframework.cloud.client.loadbalancer.Request; -import org.springframework.cloud.client.loadbalancer.Response; -import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier; -import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer; -import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; -import reactor.core.publisher.Mono; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicLong; - -/** - * LALB loadbalancer 耗时目标暂定 20ms内 TODO unit test Created by liuruisen on 2020/10/21. - */ -public class LocalityAwareLoadBalancer extends RoundRobinLoadBalancer { - - private static final Logger LOGGER = LoggerFactory.getLogger(LocalityAwareLoadBalancer.class); - - public static final String LALB_STATS_KEY = "lalb_latency_stats"; - - /** - * default weight value - */ - private static final long DEFAULT_WEIGHT = 30; - - /** - * least instance count - */ - private static final int MIN_INSTANCE_NUM = 3; - - private static final float ACTIVE_INSTANCE_RATIO = 0.7f; - - private static final int MIN_LATENCY_WINDOW = 3; - - private WeightTreeNode weightTree; - - /** - * Estimate suitable weight when calculate weight <= 0 - * - * @see #serviceInstanceWeight(LalbLatencyStats, Long) - */ - private AtomicLong maxWeight = new AtomicLong(0L); - - private ObjectProvider instanceListSupplierObjectProvider; - - public LocalityAwareLoadBalancer(ObjectProvider instancesListSupplierProvider, - String name) { - super(instancesListSupplierProvider, name); - this.weightTree = new WeightTreeNode<>(); - this.instanceListSupplierObjectProvider = instancesListSupplierProvider; - } - - @Override - public Mono> choose(Request request) { - // 经测试1000台实例耗时可维持在10ms内,先不进行异步处理 - updateWeightTree(request); - // 第一次请求 weight为0 - if (weightTree.getWeight() == 0) { - Mono> monResponse = super.choose(request); - Response loadBalancerResponse = monResponse.block(); - if (loadBalancerResponse != null) { - addLalbLatencyStats(loadBalancerResponse.getServer()); - } - return monResponse; - } - - long totalWeight = weightTree.getWeight(); - long randomWeight = ThreadLocalRandom.current().nextLong(totalWeight); - WeightTreeNode choseNode = searchNode(weightTree, randomWeight); - ServiceInstance result = choseNode.getNodeEntity(); - addLalbLatencyStats(result); - return Mono.just(new DefaultResponse(result)); - } - - protected WeightTreeNode searchNode(WeightTreeNode weightTree, long weight) { - - if (weightTree.getLeftNode() == null) { - return weightTree; - } - - if (weightTree.getRightNode() == null) { - return weightTree.getLeftNode(); - } - - if (weightTree.getLeftNode().getWeight() >= weight) { - return searchNode(weightTree.getLeftNode(), weight); - } else { - return searchNode(weightTree.getRightNode(), weight - weightTree.getLeftNode().getWeight()); - } - - } - - // 完全二叉权重树的构建 - protected synchronized void updateWeightTree(Request request) { - try { - List servers = serviceInstances(request); - if (servers != null && servers.size() > 0) { - // calculate - this.weightTree = generateWeightTreeByNodes(weightTreeNodes(servers)); - } else { - this.weightTree = new WeightTreeNode<>(); - } - } catch (Exception e) { - LOGGER.error("Update ServiceInstance weight tree error", e); - } - } - - /** - * 生成权重树节点 - * - * @param serviceInstances - * @return - */ - protected Queue> weightTreeNodes(List serviceInstances) { - Queue> weightTreeNodes = new LinkedList<>(); - - long startTime = System.currentTimeMillis(); - - if (serviceInstances != null) { - Map lalbLatencyStatsMap = new HashMap<>(); - List avgLatencies = new LinkedList<>(); - - // get all serviceInstanceStats, include requested and unrequested instances - for (ServiceInstance serviceInstance : serviceInstances) { - // 没有即创建,没有表示尚未调用到的实例[未调用到、新增实例] - StarlightStatistics statistics = - StarlightStatsManager.getOrCreateStatsByHostPort(InstanceUtils.ipPortStr(serviceInstance)); - - Stats stats = statistics.discoverStats(LALB_STATS_KEY); - if (!(stats instanceof LalbLatencyStats)) { - stats = new LalbLatencyStats(); - statistics.registerStats(LALB_STATS_KEY, stats); - } - Queue latencyWindow = ((LalbLatencyStats) stats).getLatencyWindow(); - if (latencyWindow.size() >= MIN_LATENCY_WINDOW) { - lalbLatencyStatsMap.put((LalbLatencyStats) stats, serviceInstance); - avgLatencies.add(((LalbLatencyStats) stats).avgLatency()); - } else { - // default weight - weightTreeNodes.add(new WeightTreeNode<>(serviceInstanceHashCode(serviceInstance), DEFAULT_WEIGHT, - serviceInstance)); - } - } - - LOGGER.debug("LocalityAwareRule weightTreeNodes#lalbLatencyStatsMap cost {}ms", - System.currentTimeMillis() - startTime); - - // 具有统计信息的server实例数较少,或者未达到一定比重,认为没有统计计算价值 - if (lalbLatencyStatsMap.size() < MIN_INSTANCE_NUM - || lalbLatencyStatsMap.size() * 1.0 / serviceInstances.size() < ACTIVE_INSTANCE_RATIO) { - Long execCost = System.currentTimeMillis() - startTime; - LOGGER.debug("LocalityAwareRule weightTreeNodes cost {}ms", execCost); - if (execCost > 20) { - LOGGER.warn("LocalityAwareRule weightTreeNodes cost {}ms", execCost); - } - return weightTreeNodes; - } - - // calculate the avg latency of all service instance as a benchmark - Long predictedMaxLatency = latency90Percentile(avgLatencies); - - for (Map.Entry entry : lalbLatencyStatsMap.entrySet()) { - long weight = serviceInstanceWeight(entry.getKey(), predictedMaxLatency); - weightTreeNodes - .add(new WeightTreeNode<>(serviceInstanceHashCode(entry.getValue()), weight, entry.getValue())); - } - } - Long execCost = System.currentTimeMillis() - startTime; - LOGGER.debug("LocalityAwareRule weightTreeNodes cost {}ms", execCost); - if (execCost > 20) { - LOGGER.warn("LocalityAwareRule weightTreeNodes cost {}ms", execCost); - } - - return weightTreeNodes; - } - - /** - * Calculate the latency90Percentile of all {@link ServiceInstance} below serviceId 90分位值 - * - * @param avgLatencies - * @return - */ - protected Long latency90Percentile(List avgLatencies) { - int percentileIndex = Double.valueOf(avgLatencies.size() * 0.9).intValue() - 1; - if (percentileIndex < 0) { - percentileIndex = 0; - } - Collections.sort(avgLatencies); - return avgLatencies.get(percentileIndex); - } - - /** - * Calculate the serviceInstance's weight. 归一化为100内的权重 - * - * @param stats - * @param predictedMaxLatency - * @return - */ - protected long serviceInstanceWeight(LalbLatencyStats stats, Long predictedMaxLatency) { - Long fixedWindowAvgLatency = stats.avgLatency(); - // normalization to 1-100 to prevent inaccurate calculation, plus 10ms to the predictedMaxLatency to prevent 0 - Long normalizedAvgLatency = fixedWindowAvgLatency * 100 / (predictedMaxLatency + 10); - - long serviceInstanceWeight = 100 - normalizedAvgLatency; - - // Avoid instance with a weight of 0 and no chance to access - long weight = 0; - if (serviceInstanceWeight > 0) { - weight = serviceInstanceWeight > (maxWeight.get() / 10) ? serviceInstanceWeight - : (maxWeight.get() / 10) + serviceInstanceWeight; - } else { - weight = maxWeight.get() > 0 ? (maxWeight.get() / 10) : 1; - } - - if (weight > maxWeight.get()) { - maxWeight.getAndSet(weight); - } - - return weight; - } - - /** - * Calculate the hashcode of {@link ServiceInstance} - * - * @param serviceInstance - * @return - */ - protected int serviceInstanceHashCode(ServiceInstance serviceInstance) { - return Objects.hash(serviceInstance); - } - - /** - * Generate the weight tree - * - * @param weightTreeNodes - * @return - */ - protected WeightTreeNode generateWeightTreeByNodes(Queue> weightTreeNodes) { - if (weightTreeNodes == null || weightTreeNodes.size() == 0) { - return new WeightTreeNode<>(); - } - - long nodeSize = weightTreeNodes.size(); - - if (nodeSize == 1) { - return weightTreeNodes.poll(); - } - - long startTime = System.currentTimeMillis(); - - if (nodeSize % 2 != 0) { - weightTreeNodes.add(new WeightTreeNode<>()); // transform into a complete binary tree - } - - WeightTreeNode rootNode = new WeightTreeNode<>(); - - while (weightTreeNodes.size() > 0) { - - WeightTreeNode leftChildNode = weightTreeNodes.poll(); - WeightTreeNode rightChildNode = weightTreeNodes.poll(); - - if (leftChildNode == null) { - LOGGER.warn("Left node is null, break"); - break; - } - - if (rightChildNode == null) { - rootNode = leftChildNode; // root node - break; - } - - WeightTreeNode parentNode = new WeightTreeNode<>(0, 0); - parentNode.setLeftNode(leftChildNode); - leftChildNode.setParentNode(parentNode); - - parentNode.setRightNode(rightChildNode); - rightChildNode.setParentNode(parentNode); - - parentNode.setWeight(leftChildNode.getWeight() + rightChildNode.getWeight()); - parentNode.setChildSize(2 + leftChildNode.getChildSize() + rightChildNode.getChildSize()); - - weightTreeNodes.add(parentNode); - } - - long cost = System.currentTimeMillis() - startTime; - if (cost > 20) { - LOGGER.warn("LocalityAwareRule generateWeightTreeByNodes cost {}ms", cost); - } - LOGGER.debug("LocalityAwareRule generateWeightTreeByNodes cost {}ms", cost); - return rootNode; - } - - private void addLalbLatencyStats(ServiceInstance server) { - StarlightStatistics statistics = - StarlightStatsManager.getOrCreateStatsByHostPort(InstanceUtils.ipPortStr(server)); - // putIfAbsent - statistics.registerStats(LALB_STATS_KEY, new LalbLatencyStats()); - } - - /** - * For test - * - * @return - */ - protected WeightTreeNode getWeightTree() { - return weightTree; - } - - private List serviceInstances(Request request) { - ServiceInstanceListSupplier supplier = - instanceListSupplierObjectProvider.getIfAvailable(NoopServiceInstanceListSupplier::new); - - return supplier.get(request).next().block(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/WeightTreeNode.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/WeightTreeNode.java deleted file mode 100644 index 14780623..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/lalb/WeightTreeNode.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.lalb; - -/** - * 权重树节点 Created by liuruisen on 2020/10/10. - */ -public class WeightTreeNode { - - private int hashId; - private long weight; - private WeightTreeNode parentNode; - private WeightTreeNode leftNode; - private WeightTreeNode rightNode; - private T nodeEntity; - private long childSize; - - public WeightTreeNode() { - - } - - public WeightTreeNode(int hashId, long weight) { - this.hashId = hashId; - this.weight = weight; - } - - public WeightTreeNode(int hashId, long weight, T nodeEntity) { - this.hashId = hashId; - this.weight = weight; - this.nodeEntity = nodeEntity; - } - - public long getChildSize() { - return childSize; - } - - public void setChildSize(long childSize) { - this.childSize = childSize; - } - - public int getHashId() { - return hashId; - } - - public void setHashId(int hashId) { - this.hashId = hashId; - } - - public long getWeight() { - return weight; - } - - public void setWeight(long weight) { - this.weight = weight; - } - - public WeightTreeNode getParentNode() { - return parentNode; - } - - public void setParentNode(WeightTreeNode parentNode) { - this.parentNode = parentNode; - } - - public WeightTreeNode getLeftNode() { - return leftNode; - } - - public void setLeftNode(WeightTreeNode leftNode) { - this.leftNode = leftNode; - } - - public WeightTreeNode getRightNode() { - return rightNode; - } - - public void setRightNode(WeightTreeNode rightNode) { - this.rightNode = rightNode; - } - - public T getNodeEntity() { - return nodeEntity; - } - - public void setNodeEntity(T nodeEntity) { - this.nodeEntity = nodeEntity; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("WeightTreeNode{"); - sb.append("hashId=").append(hashId); - sb.append(", weight=").append(weight); - sb.append(", childSize=").append(childSize); - if (nodeEntity != null) { - sb.append(", nodeEntity=").append(nodeEntity); - } - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/AbstractRouter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/AbstractRouter.java deleted file mode 100644 index 3362d7e7..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/AbstractRouter.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route; - -import com.baidu.cloud.starlight.springcloud.client.cluster.Router; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Created by liuruisen on 2021/10/25. - */ -public abstract class AbstractRouter implements Router { - - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractRouter.class); - - @Override - public int compareTo(Router o) { - if (o == null) { - return -1; - } - return this.getPriority() < o.getPriority() ? 1 : -1; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/DynamicRouter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/DynamicRouter.java deleted file mode 100644 index a3a3a662..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/DynamicRouter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route; - -import com.baidu.cloud.starlight.springcloud.configuration.ConfigChangeEvent; -import com.baidu.cloud.starlight.springcloud.configuration.ConfigListener; - -/** - * Created by liuruisen on 2021/10/25. - */ -public abstract class DynamicRouter extends AbstractRouter implements ConfigListener { - - @Override - public void onConfigChange(ConfigChangeEvent event) { - LOGGER.info("[XDS_ROUTE] Route config for {} changed {}", getServiceId(), event.getChangeType()); - try { - Object configContent = event.getConfigContent(); - updateConfig(configContent); - } catch (Throwable e) { - LOGGER.warn("[XDS_ROUTE] Update dynamic route configs failed, serviceId{}, configEvent {}", getServiceId(), - event, e); - } - } - - /** - * Update route config 与route方法的执行间有同步问题,需加锁 - * - * @param routeConfig - */ - public abstract void updateConfig(Object routeConfig); -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/RoutableServerListFilter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/RoutableServerListFilter.java deleted file mode 100644 index c859cc5b..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/RoutableServerListFilter.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route; - -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.StarlightServerListFilter; -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.ROUTE_SERVER_LIST_FILTER_ORDER; - -/** - * Created by liuruisen on 2021/11/3. - */ -public class RoutableServerListFilter implements StarlightServerListFilter { - - private final SingleStarlightClientManager clientManager; - - private final StarlightRouteProperties routeProperties; - - private final String name; - - public RoutableServerListFilter(SingleStarlightClientManager clientManager, - StarlightRouteProperties routeProperties, String name) { - this.clientManager = clientManager; - this.routeProperties = routeProperties; - this.name = name; - } - - @Override - public List getFilteredList(List servers) { - - if (!routeProperties.getEnabled()) { - return servers; - } - - if (servers == null || servers.size() == 0) { - return servers; - } - - Object obj = RpcContext.getContext().get(SpringCloudConstants.REQUEST_ROUTE_KEY); - if (!(obj instanceof ClusterSelector)) { - return servers; - } - - ClusterSelector clusterSelector = (ClusterSelector) obj; - - List result = new ArrayList<>(servers); - try { - result = clusterSelector.selectorClusterInstances(result); - } catch (Throwable e) { - LOGGER.error("Route select instances for serviceId {} failed, clusterSelector {}.", name, - clusterSelector.getClass().getSimpleName(), e); - return servers; - } - // 支持海若请求级的label selector选择, 用完删除防止向下传递(ugly实现) - RpcContext.getContext().remove(SpringCloudConstants.REQUEST_LABEL_SELECTOR_ROUTE_KEY); - - if ((result == null || result.isEmpty()) && InstanceUtils.isBnsServiceId(servers.get(0).getServiceId())) { - // bns 服务兜底策略,因为BNS不是标准的Gravity服务但支持了内容路由,需要进行过滤; - // 但不是所有的bns服务都配置了路由策略 - LOGGER.info("Service {} is bns type, route result is empty will return all", name); - return servers; - } - - return result; - } - - @Override - public Map getServerListFilterTasks() { - return null; - } - - @Override - public void submitTimerTask(ServiceInstance server, Integer execDelay) { - // do nothing - } - - @Override - public void destroy() { - // do nothing - } - - @Override - public SingleStarlightClientManager getSingleClientManager() { - return clientManager; - } - - @Override - public int getOrder() { - return ROUTE_SERVER_LIST_FILTER_ORDER; - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelector.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelector.java deleted file mode 100644 index fff196f2..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelector.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label; - -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match.LabelParser; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match.LabelSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match.LabelSelectorRequirement; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Migrate from gravity and extend ClusterSelector - */ -public class LabelClusterSelector extends ClusterSelector { - - private static final Logger LOG = LoggerFactory.getLogger(LabelClusterSelector.class); - - private LabelParser labelParser = new LabelParser(); - - @Override - public List selectorClusterInstances(List originList) { - if (originList == null || originList.isEmpty()) { - return originList; - } - - String labelSelector = getMeta().get(SpringCloudConstants.LABEL_SELECTOR_ROUTE_KEY); - - if (StringUtils.isEmpty(labelSelector)) { - return originList; - } - - List result = originList; - try { - LabelSelector selector = labelParser.parse(labelSelector); - if (selector.getMatchExpressions() != null) { - result = originList.stream().filter(server -> matchLabels(server, selector.getMatchExpressions())) - .collect(Collectors.toList()); - recordSelectorResult(labelSelector, originList, result); - } - } catch (Throwable e) { - LOG.error("[LABEL_ROUTE]LabelClusterSelector#selectorClusterInstances failed, service: {}, label: {}", - getServiceId(), labelSelector, e); - } - - if (result == null || result.isEmpty()) { - recordSelectorEmptyResult(labelSelector, originList); - } - - return result; - } - - private boolean matchLabels(ServiceInstance server, List expressions) { - for (LabelSelectorRequirement expression : expressions) { - if (!matchLabel(server, expression)) { - return false; - } - } - return true; - } - - private boolean matchLabel(ServiceInstance server, LabelSelectorRequirement expression) { - if ("namespace".equals(expression.getKey())) { - // 直接返回true, gravity服务发现时会携带namespace信息,保证发现的服务为指定ns下的 - // NOTICE: 仅适用gravity场景 - return true; - } - Map meta = getServerMeta(server); - String value = meta != null ? meta.get(expression.getKey()) : null; - return expression.labelValueMatch(value); - } - - private void recordSelectorEmptyResult(String labelSelector, List origin) { - LOG.info("[LABEL_ROUTE]The filtered servers is empty, serviceId:{}, label:{}, originServers:{}", getServiceId(), - labelSelector, origin); - } - - private void recordSelectorResult(String labelSelector, List origin, - List result) { - LOG.debug("[LABEL_ROUTE]Filter servers of service: {} by label: {}, servers: {}/{}, {}", getServiceId(), - labelSelector, origin.size(), result.size(), - result.stream().map(ServiceInstance::getInstanceId).collect(Collectors.joining(","))); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouter.java deleted file mode 100644 index d6d1a96b..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.springcloud.client.cluster.Cluster; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.cluster.route.AbstractRouter; -import com.baidu.cloud.starlight.springcloud.client.cluster.subcluster.DefaultCluster; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.RouteUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by liuruisen on 2021/12/7. - */ -public class LabelSelectorRouter extends AbstractRouter { - - private static final Logger LOGGER = LoggerFactory.getLogger(LabelSelectorRouter.class); - - private static final Integer PRIORITY = Integer.MAX_VALUE - 1; - - private final String serviceId; - - private final LoadBalancer loadBalancer; - - private final StarlightRouteProperties routeProperties; - - private final StarlightClientProperties clientProperties; - - public LabelSelectorRouter(String serviceId, StarlightRouteProperties routeProperties, - StarlightClientProperties clientProperties, LoadBalancer loadBalancer) { - this.serviceId = serviceId; - this.routeProperties = routeProperties; - this.clientProperties = clientProperties; - this.loadBalancer = loadBalancer; - } - - @Override - public Cluster route(Request request) { - long routeStart = System.currentTimeMillis(); - // TODO 后续可考虑用RDS支持label路由 - // 支持海若请求级的label selector选择, 用完删除防止向下传递(ugly实现) - Map routeContext = - (Map) request.getNoneAdditionKv().get(SpringCloudConstants.ROUTE_CONTEXT_KEY); - LOGGER.debug("LabelSelectorRouter route context {}", routeContext); - String labelSelector = (String) routeContext.get(SpringCloudConstants.REQUEST_LABEL_SELECTOR_ROUTE_KEY); - LOGGER.debug("LabelSelectorRouter label selector from route context {}", labelSelector); - if (StringUtils.isEmpty(labelSelector)) { - labelSelector = routeProperties.getServiceLabelSelector(getRouteServiceId()); - } - if (StringUtils.isEmpty(labelSelector)) { - LOGGER.debug("[LABEL_ROUTE]LabelSelector for service {} is empty", getServiceId()); - labelSelector = ""; - } - - ClusterSelector clusterSelector = new LabelClusterSelector(); - clusterSelector.setServiceId(getServiceId()); - clusterSelector.setClusterName(getServiceId()); - - Map clusterLabels = new HashMap<>(); - clusterLabels.put(SpringCloudConstants.LABEL_SELECTOR_ROUTE_KEY, labelSelector); - clusterSelector.setMeta(clusterLabels); - - recordRouteMatch(request, labelSelector, routeStart); - - return new DefaultCluster(clusterSelector, clientProperties, loadBalancer); - } - - @Override - public int getPriority() { - return PRIORITY; - } - - @Override - public String getServiceId() { - return this.serviceId; - } - - @Override - public String getRouteServiceId() { - // 配置了map映射,使用map指定的value - if (routeProperties.getServiceIdMap() != null && routeProperties.getServiceIdMap().containsKey(serviceId)) { - return routeProperties.getServiceIdMap().get(serviceId); - } - return this.serviceId; - } - - private void recordRouteMatch(Request request, String labelSelector, long routeStart) { - LOGGER.info( - "[LABEL_ROUTE] Request matched label-selector route: " + "serviceId {}, req{}, labelSelector {}, cost {}", - getServiceId(), RouteUtils.reqMsg(request), labelSelector, System.currentTimeMillis() - routeStart); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelOperator.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelOperator.java deleted file mode 100644 index c202f7b5..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelOperator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match; - -/** - * Migrate from gravity labelselector - */ -public enum LabelOperator { - - NOT_EQUAL("!="), EQUAL("="), NOT_IN(" not in"), IN(" in"); - - private String operator; - - LabelOperator(String operator) { - this.operator = operator; - } - - public String getOperator() { - return operator; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelParser.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelParser.java deleted file mode 100644 index 52f4ff5a..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelParser.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match; - -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * Migrate from gravity label selector - */ -public class LabelParser { - - public LabelSelector parse(String label) { - if (StringUtils.isEmpty(label)) { - return null; - } - // 简单处理,&&分隔 - String[] labels = label.split("&&"); - - List lsr = - Arrays.stream(labels).map(this::doParse).filter(Objects::nonNull).collect(Collectors.toList()); - - LabelSelector ls = new LabelSelector(); - ls.setMatchExpressions(lsr); - return ls; - } - - private LabelSelectorRequirement doParse(String label) { - - label = label.trim(); - - for (LabelOperator operator : LabelOperator.values()) { - if (label.contains(operator.getOperator())) { - String[] labelSplit = label.split(operator.getOperator(), 2); - if (labelSplit.length != 2) { - return null; - } - String lhs = labelSplit[0].trim(); - String rhs = labelSplit[1].trim(); - // rhs去掉括号 - rhs = rhs.replaceAll("^\\(", "").replaceAll("\\)$", ""); - - LabelSelectorRequirement ls = new LabelSelectorRequirement(); - ls.setKey(lhs); - ls.setOperator(operator); - ls.setValues(Arrays.stream(rhs.split(",")).map(String::trim).collect(Collectors.toList())); - - return ls; - } - } - return null; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelector.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelector.java deleted file mode 100644 index ea05377f..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelector.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match; - -import java.util.List; - -/** - * Migrate from gravity label selector - */ -public class LabelSelector { - - private List matchExpressions; - - public List getMatchExpressions() { - return matchExpressions; - } - - public void setMatchExpressions(List matchExpressions) { - this.matchExpressions = matchExpressions; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelectorRequirement.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelectorRequirement.java deleted file mode 100644 index 1b3cb1f8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/match/LabelSelectorRequirement.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label.match; - -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; - -import java.util.List; - -/** - * Migrate from gravity label selector - */ -public class LabelSelectorRequirement { - - private String key; - private LabelOperator operator; - private List values; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public LabelOperator getOperator() { - return operator; - } - - public void setOperator(LabelOperator operator) { - this.operator = operator; - } - - public List getValues() { - return values; - } - - public void setValues(List values) { - this.values = values; - } - - public boolean labelValueMatch(String actual) { - switch (operator) { - case EQUAL: - return !values.isEmpty() && StringUtils.isNotBlank(actual) && actual.equals(values.get(0)); - case NOT_EQUAL: - return StringUtils.isBlank(actual) || !actual.equals(values.get(0)); - case IN: - return StringUtils.isNotBlank(actual) && values.contains(actual); - case NOT_IN: - return StringUtils.isBlank(actual) || !values.contains(actual); - default: - return true; - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/subcluster/DefaultCluster.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/subcluster/DefaultCluster.java deleted file mode 100644 index 07a9c0d8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/cluster/subcluster/DefaultCluster.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.subcluster; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.starlight.protocol.stargate.StargateProtocol; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import com.baidu.cloud.starlight.springcloud.client.cluster.Cluster; -import com.baidu.cloud.starlight.springcloud.client.cluster.ClusterSelector; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.OutlierConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.thirdparty.jackson.core.type.TypeReference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.ServiceInstance; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Created by liuruisen on 2021/9/26. - */ -public class DefaultCluster implements Cluster { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCluster.class); - - private ClusterSelector clusterSelector; - - // NOTICE 支持修改lb后, 进行更改线程和使用线程的并发控制 - private LoadBalancer loadBalancer; - - private volatile Map, ServiceConfig> serviceRefers; - - // 客户端集群全局配置 - private StarlightClientProperties globalConfig; - - public DefaultCluster(ClusterSelector clusterSelector, StarlightClientProperties globalConfig, - LoadBalancer loadBalancer) { - this.clusterSelector = clusterSelector; - this.serviceRefers = new ConcurrentHashMap<>(); - this.globalConfig = globalConfig; - this.loadBalancer = loadBalancer; - } - - @Override - public LoadBalancer getLoadBalancer() { - return loadBalancer; - } - - @Override - public void setServiceRefers(Map, ServiceConfig> referServices) { - this.serviceRefers = referServices; - } - - @Override - public ClusterSelector getClusterSelector() { - return clusterSelector; - } - - @Override - public void execute(Request request, RpcCallback callback) { - // select instance - long starTime = System.currentTimeMillis(); - ServiceInstance instance = getLoadBalancer().choose(clusterSelector); - LOGGER.debug("Select instance from ribbon cost: {}", System.currentTimeMillis() - starTime); - if (instance == null) { - throw new StarlightRpcException(SpringCloudConstants.NO_INSTANCE_ERROR_CODE, - "No instances available for service " + getClusterSelector().getServiceId() + ", cluster " - + getClusterSelector().getClusterName()); - } - - SingleStarlightClient starlightClient = null; - try { - starlightClient = initSingleClient(instance.getHost(), instance.getPort()); - } catch (Exception e) { - // 有可能无法走到凤睛切面所在的逻辑,导致span信息里无remoteIp,这里设置上 - RpcContext.getContext().setRemoteAddress(instance.getHost(), instance.getPort()); - LOGGER.warn("AbstractClusterClient unexpect error ", e); - callback.onError(e); - return; - } - - // request protocol - ServiceConfig serviceConfig = request.getServiceConfig(); - if (serviceConfig == null) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The request service has not been refer, please call refer() before request, " + "service {" - + request.getServiceClass().getName() + "}"); - } - if (!StringUtils.isEquals(request.getProtocolName(), SpringRestSseProtocol.PROTOCOL_NAME)) { - String protocolName = requestProtocol(serviceConfig, instance); - request.setProtocolName(protocolName); - } - - // stargate group & version - // Temporary plan for migration stargate - addStargateMetadata(request, serviceConfig, instance); - - // execute request - try { - // 在此处执行调用主要为了兼容spring cloud的逻辑,不兼容是否可以;附带执行一些cluster特有逻辑 - getLoadBalancer().execute(clusterSelector, starlightClient, instance, request, callback); - } catch (Throwable e) { - // 有可能无法走到凤睛切面所在的逻辑,导致span信息里无remoteIp,这里设置上 - RpcContext.getContext().setRemoteAddress(instance.getHost(), instance.getPort()); - callback.onError(new StarlightRpcException(StarlightRpcException.INTERNAL_SERVER_ERROR, - "Request failed: " + e.getMessage())); - } - } - - /** - * Protocol selection When no protocol is specified, the protocol selection strategy will be adopted. - */ - private String requestProtocol(ServiceConfig serviceConfig, ServiceInstance instance) { - String protocolName = serviceConfig.getProtocol(); - if (StringUtils.isEmpty(protocolName)) { - if (instance.getMetadata() == null || instance.getMetadata().size() == 0 - || StringUtils.isEmpty(instance.getMetadata().get(SpringCloudConstants.PROTOCOLS_KEY))) { - LOGGER.warn("Unable to select protocol for request: " - + "there is nor protocol message in registration message or in configuration." - + "Will use the default protocol brpc"); - protocolName = Constants.BRPC_VALUE; - } else { - String protocols = instance.getMetadata().get(SpringCloudConstants.PROTOCOLS_KEY); - protocolName = protocols.split(",")[0]; - } - } - - return protocolName; - } - - /** - * when call stargate provider, request need to take version and group information - */ - private void addStargateMetadata(Request request, ServiceConfig serviceConfig, ServiceInstance instance) { - - if (!request.getProtocolName().equals(StargateProtocol.PROTOCOL_NAME)) { - return; - } - - if (instance.getMetadata() == null || instance.getMetadata().size() <= 0) { - return; - } - - if (StringUtils.isEmpty(instance.getMetadata().get(SpringCloudConstants.INTERFACES_KEY))) { - LOGGER.warn( - "Request service {} method {} protocol stargate. " - + "There is no interfaces message in registration message, " - + "will use default group[normal] and version[1.0.0]", - request.getServiceName(), request.getMethodName()); - return; - } - - String interfaceStr = instance.getMetadata().get(SpringCloudConstants.INTERFACES_KEY); - if (!interfaceStr.contains(request.getServiceClass().getName())) { - LOGGER.warn( - "Request service {}, method {}, protocol stargate, interface metadata {}. " - + "The registration interfaces metadata dose not contain the service, " - + "will use default group[normal] and version[1.0.0]. ", - request.getServiceClass().getName(), request.getMethodName(), interfaceStr); - return; - } - - try { - List interfaces = - JsonSerializer.OBJECT_MAPPER.readValue(interfaceStr, new TypeReference>() {}); - - if (interfaces == null || interfaces.size() == 0) { - LOGGER.warn( - "Request service {}, method {}, protocol stargate, interface metadata {}. " - + "The result of parsing registration interfaces metadata is empty, " - + "will use default group[normal] and version[1.0.0]. ", - request.getServiceClass().getName(), request.getMethodName(), interfaceStr); - return; - } - - for (String interfaceName : interfaces) { - if (interfaceName.contains(request.getServiceClass().getName())) { - String[] metadata = interfaceName.split(":"); - if (metadata.length != 3) { - LOGGER.warn( - "Request service {}, method {}, protocol stargate, interface {}. " - + "The interface info parse from registration metadata is illegal, " - + "will use default group[normal] and version[1.0.0]. ", - request.getServiceClass().getName(), request.getMethodName(), interfaceName); - return; - } - serviceConfig.setGroup(metadata[0]); - serviceConfig.setVersion(metadata[2]); - LOGGER.debug("Request service {}, method {} use protocol {}, group is {}, version is {}", - request.getServiceName(), request.getMethodName(), request.getProtocolName(), - serviceConfig.getGroup(), serviceConfig.getVersion()); - return; - } - } - - LOGGER.debug( - "Request service {}, method {}, protocol stargate, interfaces {}. " - + "The interface list parse from metadata do not contain the request service, " - + "will use default group[normal] and version[1.0.0]. ", - request.getServiceClass().getName(), request.getMethodName(), interfaces); - } catch (IOException e) { - throw new IllegalStateException( - "Cannot use stargate to send request, " + "parse interfaces metadata failed, interface metadata " - + interfaceStr + " please check provider registration metadata"); - } - } - - /** - * 可被继承,做些动态修改client配置的操作 - * - * @param host - * @param port - * @return - */ - protected SingleStarlightClient initSingleClient(String host, Integer port) { - TransportConfig transportConfig = globalConfig.transportConfig(clusterSelector.getServiceId()); - transportConfig.setAdditional(clientConfigMap()); - // init - return SingleStarlightClientManager.getInstance().getOrCreateSingleClient(host, port, transportConfig, - serviceRefers); - } - - /** - * 依据配置信息,生成uri中的attachment信息 可用于动态修改uri中的配置,并为后续流程生效 - * - * @return - */ - protected Map clientConfigMap() { - Map configAdd = new HashMap<>(); - OutlierConfig outlierConfig = globalConfig.getOutlierConfig(clusterSelector.getServiceId()); - if (outlierConfig != null) { - configAdd.put(SpringCloudConstants.OUTLIER_DETECT_ENABLED_KEY, String.valueOf(outlierConfig.getEnabled())); - configAdd.put(SpringCloudConstants.OUTLIER_DETECT_INTERVAL_KEY, - String.valueOf(outlierConfig.getDetectInterval())); - configAdd.put(SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM_KEY, - String.valueOf(outlierConfig.getFailurePercentMinRequest())); - configAdd.put(SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY, - String.valueOf(outlierConfig.getFailurePercentThreshold())); - - if (outlierConfig.getFailureCountThreshold() != null) { - configAdd.put(SpringCloudConstants.OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY, - String.valueOf(outlierConfig.getFailureCountThreshold())); - } - } - - return configAdd; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEvent.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEvent.java deleted file mode 100644 index b5e4f068..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEvent.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -/** - * Record outlier reason Created by liuruisen on 2021/9/6. - */ -public class OutlierDetectEvent { - - private Integer detectInterval; - - private Integer reqCount; - - private Integer succReqCount; - - private Integer failCount; - - private Integer detectFailCount; - - private Integer failPercent; - - private Integer detectFailPercent; - - public Integer getDetectInterval() { - return detectInterval; - } - - public void setDetectInterval(Integer detectInterval) { - this.detectInterval = detectInterval; - } - - public Integer getReqCount() { - return reqCount; - } - - public void setReqCount(Integer reqCount) { - this.reqCount = reqCount; - } - - public Integer getSuccReqCount() { - return succReqCount; - } - - public void setSuccReqCount(Integer succReqCount) { - this.succReqCount = succReqCount; - } - - public Integer getFailCount() { - return failCount; - } - - public void setFailCount(Integer failCount) { - this.failCount = failCount; - } - - public Integer getFailPercent() { - return failPercent; - } - - public void setFailPercent(Integer failPercent) { - this.failPercent = failPercent; - } - - public Integer getDetectFailCount() { - return detectFailCount; - } - - public void setDetectFailCount(Integer detectFailCount) { - this.detectFailCount = detectFailCount; - } - - public Integer getDetectFailPercent() { - return detectFailPercent; - } - - public void setDetectFailPercent(Integer detectFailPercent) { - this.detectFailPercent = detectFailPercent; - } - - public String outlierReason() { - StringBuilder builder = new StringBuilder(); - builder.append("["); - builder.append("interval " + getDetectInterval() + "s, "); - builder.append("reqcnt " + getReqCount() + ", "); - builder.append("succcnt " + getSuccReqCount() + ", "); - if (getDetectFailCount() != null) { - builder.append("failcnt(trh" + getDetectFailCount() + ") " + getFailCount() + ", "); - } else { - builder.append("failcnt " + getFailCount() + ", "); - } - if (getDetectFailPercent() != null) { - builder.append("failpct(trh" + getDetectFailPercent() + "%) " + getFailPercent() + "%"); - } - builder.append("]"); - - return builder.toString(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilter.java deleted file mode 100644 index 0b952416..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilter.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.statistics.CountStats; -import com.baidu.cloud.starlight.api.statistics.Stats; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.statistics.FixedTimeWindowStats; -import com.baidu.cloud.starlight.core.statistics.StarlightStatistics; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_ENABLED; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_ENABLED_KEY; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_INTERVAL; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_INTERVAL_KEY; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM; -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM_KEY; - -/** - * Detect outlier based on statistics, used is client side. - *

- * Created by liuruisen on 2021/4/20. - */ -public class OutlierDetectFilter implements Filter { - - private static final Logger LOGGER = LoggerFactory.getLogger(OutlierDetectFilter.class); - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - try { - configureOutlier(request); - } catch (Throwable e) { - LOGGER.warn("OutlierDetectFilter filterRequest failed. ", e); - } - - // do nothing - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - - try { - SingleStarlightClientManager starlightClientManager = SingleStarlightClientManager.getInstance(); - - // detect un health outlier & update SingleStarlightClient status - URI remoteURI = request.getRemoteURI(); - if (remoteURI == null) { - LOGGER.warn("OutlierFilter cannot find the statistics, because remote uri is null"); - return; - } - - boolean outlierEnable = remoteURI.getParameter(OUTLIER_DETECT_ENABLED_KEY, OUTLIER_DETECT_ENABLED); - if (!outlierEnable) { - return; - } - - StarlightStatistics statistics = StarlightStatsManager.getStats(remoteURI); - if (statistics == null) { - LOGGER.warn("OutlierFilter cannot find the statistics of {} from StarlightStatsManager", - remoteURI.getAddress()); - return; - } - - Stats stats = statistics.discoverStats(SpringCloudConstants.OUTLIER_STATS_KEY); - if (!(stats instanceof CountStats)) { - LOGGER.warn("OutlierFilter cannot find the fixed time window statistics of {}", remoteURI.getAddress()); - return; - } - - CountStats outlierStats = (CountStats) stats; - Integer outlierMinReqNum = - remoteURI.getParameter(OUTLIER_DETECT_MINI_REQUEST_NUM_KEY, OUTLIER_DETECT_MINI_REQUEST_NUM); - - Integer totalReqCount = outlierStats.totalReqCount(); - Integer failReqCount = outlierStats.failReqCount(); - if (totalReqCount < outlierMinReqNum) { // less than outlier detect threshold, return - return; - } - - String outlierDetectFailCount = remoteURI.getParameter(OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY); - if (!StringUtils.isEmpty(outlierDetectFailCount)) { - int outlierFailCount = Integer.parseInt(outlierDetectFailCount); - if (failReqCount >= outlierFailCount) { - markOutlier(remoteURI, starlightClientManager, outlierStats); - } - } else { - int outlierDetectFailPercent = remoteURI.getParameter(OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY, - OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD); - int failPercent = failPercent(failReqCount, totalReqCount); - if (failPercent > outlierDetectFailPercent) { // Failure threshold exceeded, mark client as outlier - markOutlier(remoteURI, starlightClientManager, outlierStats); - } - } - } catch (Throwable throwable) { - LOGGER.warn("OutlierDetectFilter filterResponse failed. ", throwable); - } - - } - - private void markOutlier(URI remoteURI, SingleStarlightClientManager starlightClientManager, - CountStats outlierStats) { - SingleStarlightClient singleClient = - starlightClientManager.getSingleClient(remoteURI.getHost(), remoteURI.getPort()); - if (singleClient == null) { - LOGGER.warn( - "Statistics of {} is exist in StatisticsManager, " - + "but SingleStarlightClient associated with it is not exist in ClientManager", - remoteURI.getAddress()); - return; - } - - // Configured detect fail count, maybe null - Integer detectFailCount = null; - String outlierDetectFailCount = remoteURI.getParameter(OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY); - if (!StringUtils.isEmpty(outlierDetectFailCount)) { - detectFailCount = Integer.parseInt(outlierDetectFailCount); - } - - // Configured detect interval - int detectInterval = remoteURI.getParameter(OUTLIER_DETECT_INTERVAL_KEY, OUTLIER_DETECT_INTERVAL); - - // Configured detect percent, maybe null - Integer detectFailPercent = null; - String outlierDetectFailPct = remoteURI.getParameter(OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY); - if (!StringUtils.isEmpty(outlierDetectFailPct)) { - detectFailPercent = Integer.parseInt(outlierDetectFailPct); - } - - int failPercent = failPercent(outlierStats.failReqCount(), outlierStats.totalReqCount()); - - OutlierDetectEvent detectEvent = new OutlierDetectEvent(); - detectEvent.setReqCount(outlierStats.totalReqCount()); - detectEvent.setSuccReqCount(outlierStats.sucReqCount()); - detectEvent.setFailCount(outlierStats.failReqCount()); - detectEvent.setDetectFailCount(detectFailCount); - detectEvent.setDetectFailPercent(detectFailPercent); - detectEvent.setFailPercent(failPercent); - detectEvent.setDetectInterval(detectInterval); - - // update client status to OUTLIER - PeerStatus peerStatus = new PeerStatus(PeerStatus.Status.OUTLIER, System.currentTimeMillis()); - peerStatus.setStatusReason(detectEvent); - singleClient.updateStatus(peerStatus); - } - - private int failPercent(int failReqCount, int totalReqCount) { - return (int) ((failReqCount * 0.1) / (totalReqCount * 0.1) * 100); - } - - /** - * configure outlier - * - * @param request - */ - private void configureOutlier(Request request) { - URI remoteURI = request.getRemoteURI(); - StarlightStatistics statistics = StarlightStatsManager.getOrCreateStats(remoteURI); - boolean outlierEnable = remoteURI.getParameter(OUTLIER_DETECT_ENABLED_KEY, OUTLIER_DETECT_ENABLED); - if (!outlierEnable) { - return; - } - - int detectInterval = remoteURI.getParameter(OUTLIER_DETECT_INTERVAL_KEY, OUTLIER_DETECT_INTERVAL); - if (statistics.discoverStats(SpringCloudConstants.OUTLIER_STATS_KEY) == null) { - FixedTimeWindowStats outlierStats = new FixedTimeWindowStats(detectInterval); - statistics.registerStats(SpringCloudConstants.OUTLIER_STATS_KEY, outlierStats); - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilter.java deleted file mode 100644 index faf6fa86..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilter.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.heartbeat.Heartbeat; -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatRpcRequestHolder; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.OutlierConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.StarlightServerListFilter; -import com.baidu.cloud.starlight.springcloud.common.ClusterLogUtils; -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import static com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants.OUTLIER_SEVER_LIST_FILTER_ORDER; - -/** - * Eject outlier instance - *

- * Created by liuruisen on 2021/4/22. - */ -public class OutlierEjectServerListFilter implements StarlightServerListFilter { - - private static final Integer OUTLIER_LOG_RECORD_DURATION = 30000; - - private static final String FORCED_RECOVERY_HEALTH = "forced recovery as configured"; - - private static final String RECOVERY_HEALTH = "recovery because detected health"; - - private static final String RECOVERY_FAIL = "3 consecutive tests failed"; - - private final SingleStarlightClientManager singleStarlightClientManager; - - private final StarlightClientProperties clientProperties; - - private final Map outlierRecoverTasks; - - private final String clientName; - - public OutlierEjectServerListFilter(SingleStarlightClientManager clientManager, - StarlightClientProperties clientProperties, String clientName) { - this.singleStarlightClientManager = clientManager; // not null - this.clientProperties = clientProperties; // not null - this.clientName = clientName; - this.outlierRecoverTasks = new ConcurrentHashMap<>(); - } - - @Override - public List getFilteredList(List originList) { - long startTime = System.currentTimeMillis(); - // 修正下异常实例自动恢复任务,应对异常实例重启等情况 - reviseOutlierTask(); - - int originSize = originList.size(); - if (originSize <= 1) { // size less than 1, return - LOGGER.info("Original server instance size is {}, less than or equals 1 will not eject.", originList); - return originList; - } - - String clientName = getClientName(); - OutlierConfig outlierConfig = clientProperties.getOutlierConfig(clientName); - if (!outlierConfig.getEnabled()) { // not enabled, return - return originList; - } - - List filtered = new LinkedList<>(originList); - try { - double maxEjectCountDouble = (((double) outlierConfig.getMaxEjectPercent() / 100) * originSize); - if (maxEjectCountDouble < 0.5d) { - LOGGER.info("Max eject count of {} is 0, max eject double {}, origin size {}, maxEjectPercent {}", - getClientName(), maxEjectCountDouble, originSize, outlierConfig.getMaxEjectPercent()); - } - int maxEjectCount = (int) Math.round(maxEjectCountDouble); - int ejectCount = 0; - for (ServiceInstance server : originList) { - if (ejectCount >= maxEjectCount) { - LOGGER.info("Reach the max eject count {}, will not eject.", maxEjectCount); - break; - } - - SingleStarlightClient client = - singleStarlightClientManager.getSingleClient(server.getHost(), server.getPort()); - // not use this server instance, not filter - if (client == null) { - continue; - } - - if (client.getStatus() == null) { - continue; - } - - // outlier, remove from the server list - if (PeerStatus.Status.OUTLIER.equals(client.getStatus().getStatus())) { - filtered.remove(server); - ejectCount++; - if ((System.currentTimeMillis() - - client.getStatus().getStatusRecordTime()) < OUTLIER_LOG_RECORD_DURATION) { - ClusterLogUtils.logOutlierInstanceEject(LOGGER, getClientName(), server, client.getStatus()); - } - // detect recover - submitTimerTask(server, outlierConfig.getBaseEjectTime()); - } - } - if (ejectCount > 0) { - // 记录本provider当前被摘除的实例个数 - ClusterLogUtils.logOutlierAppEject(LOGGER, getClientName(), originSize, ejectCount, maxEjectCount); - } - } catch (Throwable e) { - LOGGER.warn("OutlierEjectServerListFilter getFilteredList failed, will use all instances, " + "caused by ", - e); - } - LOGGER.debug("OutlierEjectServerListFilter getFilteredList cost {}", System.currentTimeMillis() - startTime); - return filtered; - } - - @Override - public SingleStarlightClientManager getSingleClientManager() { - return this.singleStarlightClientManager; - } - - @Override - public int getOrder() { - return OUTLIER_SEVER_LIST_FILTER_ORDER; - } - - @Override - public Map getServerListFilterTasks() { - return this.outlierRecoverTasks; - } - - @Override - public synchronized void submitTimerTask(ServiceInstance server, Integer ejectTime) { - String clientName = getClientName(); - OutlierConfig outlierConfig = clientProperties.getOutlierConfig(clientName); - - if (outlierRecoverTasks.get(InstanceUtils.ipPortStr(server)) != null - && outlierConfig.getBaseEjectTime().equals(ejectTime)) { - return; - } - - LOGGER.debug("Add new detect timer server {}, eject time {}s", InstanceUtils.ipPortStr(server), ejectTime); - Timeout timeout = SERVER_LIST_FILTER_TIMER.newTimeout(new OutlierRecoverTask(server, ejectTime, outlierConfig), - ejectTime, TimeUnit.SECONDS); - outlierRecoverTasks.put(InstanceUtils.ipPortStr(server), timeout); - } - - @Override - public void destroy() { - if (outlierRecoverTasks.size() > 0) { - for (Map.Entry task : outlierRecoverTasks.entrySet()) { - if (task != null && task.getValue() != null) { - task.getValue().cancel(); - } - } - } - } - - private void reviseOutlierTask() { - if (outlierRecoverTasks.isEmpty()) { - return; - } - Map readOnlyTasks = Collections.unmodifiableMap(outlierRecoverTasks); - for (Map.Entry entry : readOnlyTasks.entrySet()) { - try { - String[] hostPort = entry.getKey().split(":"); - String host = hostPort[0]; - String port = hostPort[1]; - SingleStarlightClient client = - singleStarlightClientManager.getSingleClient(host, Integer.valueOf(port)); - // client为空,表示这个应用已经下线清理,修正下异常实例恢复任务 - if (client == null) { - Timeout timeout = outlierRecoverTasks.remove(entry.getKey()); - timeout.cancel(); - continue; - } - // 非OUTLIER状态,重启了或者重新上线,修正下异常实例恢复任务 - if (!PeerStatus.Status.OUTLIER.equals(client.getStatus().getStatus())) { - Timeout timeout = outlierRecoverTasks.remove(entry.getKey()); - timeout.cancel(); - } - } catch (Exception e) { - LOGGER.warn("Revise outlier task failed, hostPort {}, errorMsg {}", entry.getKey(), e.getMessage()); - } - } - } - - private String getClientName() { - return clientName; - } - - private class OutlierRecoverTask implements TimerTask { - - private final ServiceInstance server; - - private final OutlierConfig outlierConfig; - - private final Integer lastEjectTime; - - public OutlierRecoverTask(ServiceInstance server, Integer lastEjectTime, OutlierConfig outlierConfig) { - this.server = server; - this.outlierConfig = outlierConfig; - this.lastEjectTime = lastEjectTime; - } - - @Override - public void run(Timeout timeout) throws Exception { - SingleStarlightClient singleClient = - singleStarlightClientManager.getSingleClient(server.getHost(), server.getPort()); - if (singleClient == null) { // removed client, the service instance is offline - return; - } - - if (!PeerStatus.Status.OUTLIER.equals(singleClient.getStatus().getStatus())) { - return; // the status is not OUTLIER, return - } - - if (!outlierConfig.getRecoverByCheckEnabled()) { - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - getServerListFilterTasks().remove(InstanceUtils.ipPortStr(server)); - ClusterLogUtils.logOutlierRecoverySucc(LOGGER, getClientName(), server, FORCED_RECOVERY_HEALTH, - lastEjectTime); - return; - } - - // request heartbeat - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setInvokeTimeoutMills(SpringCloudConstants.HEARTBEAT_REQUEST_TIMEOUT); - - int heartbeatSucCount = 0; - for (int i = 0; i < 3; i++) { // try detect 3 times - RpcRequest heartbeatReq = HeartbeatRpcRequestHolder.heartbeatRequest(); - heartbeatReq.setServiceConfig(serviceConfig); - try { - ResultFuture resultFuture = new ResultFuture(); - RpcCallback rpcCallback = new FutureCallback(resultFuture, heartbeatReq); - singleClient.request(heartbeatReq, rpcCallback); - Object result = resultFuture.get(); - - if (result instanceof Heartbeat && Constants.PONG.equals(((Heartbeat) result).getMessage())) { - heartbeatSucCount++; - } else { - LOGGER.warn("Outlier recover heartbeat receive response from {} success, " - + "but message is not correct {}", InstanceUtils.ipPortStr(server), result); - } - } catch (Throwable exp) { - if (exp instanceof StarlightRpcException) { - StarlightRpcException rpcException = (StarlightRpcException) exp; - // Compatible with the old version - // Old version starlight server will return SERVICE_NOT_FOUND_EXCEPTION - // because it dose not export HeartbeatService - if (StarlightRpcException.SERVICE_NOT_FOUND_EXCEPTION.equals(rpcException.getCode())) { - heartbeatSucCount++; - } - } - } - } - - if (heartbeatSucCount >= 3) { // success - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - getServerListFilterTasks().remove(InstanceUtils.ipPortStr(server)); - ClusterLogUtils.logOutlierRecoverySucc(LOGGER, getClientName(), server, RECOVERY_HEALTH, lastEjectTime); - } else { // fail - // Accumulate the detection time of recover - int nextEjectTime = lastEjectTime + outlierConfig.getBaseEjectTime(); - if (nextEjectTime > outlierConfig.getMaxEjectTime()) { - nextEjectTime = outlierConfig.getMaxEjectTime(); - } - ClusterLogUtils.logOutlierRecoveryFail(LOGGER, getClientName(), server, RECOVERY_FAIL, lastEjectTime, - nextEjectTime); - // resubmit task - submitTimerTask(server, nextEjectTime); - } - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfig.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfig.java deleted file mode 100644 index 672b1ad5..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfig.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import java.util.HashMap; -import java.util.Map; - -/** - * application level config - */ -public class ClientConfig { - - private String protocol; - - private String compressType; // default none - - private String filters; // split by "," - - private String clusterModel; // default SpringCloudConstants.DEFAULT_CLUSTER_MODEL application level - - private Boolean warmUpEnabled; - - // warm up ratio, used to warm up ClusterStarlightClient - private Integer warmUpRatio; // default SpringCloudConstants.DEFAULT_WARM_UP_RATIO - - private Integer warmUpCount; // same as warmUpRatio, prior than warmUpRatio - - private Integer connectTimeoutMills; - - private Integer writeTimeoutMills; // default Constants.WRITE_TIMEOUT_VALUE; - - private Integer requestTimeoutMills; // default Constants.REQUEST_TIMEOUT_VALUE; - - private Integer readIdleTimeout; // default Constants.READ_IDLE_TIMEOUT_VALUE; // second - - private Integer maxHeartbeatTimes; // default Constants.MAX_HEARTBEAT_TIMES_VALUE; - - private Integer ioThreadNum; - - private String channelType; // default Constants.DEFAULT_RPC_CHANNEL_TYPE_VALUE; - - private Integer maxConnections; - - private Integer maxIdleConnections; - - private Integer minIdleConnections; - - private Integer retryTimes; // application level - - private String retryMethods; // application level - - private String retryErrorCodes; // split by , - - /** - * The time unit of the time interval between two retries, which will be used to calculate the true delay time. - */ - private Integer retryDelayTimeUnitMills; // application level - - /** - * Only used in brpc protocol currently - * - * "pb2-std": metadata proto2, body proto2 "pb2-java": meta proto2, body preserve null - */ - private String serializeMode; - - /** - * Whether to enable connection keep-alive capability. Default is false - */ - private Boolean connectKeepAliveEnable; - - private Integer networkErrorRetryTimes; - - /** - * The config of outlier detect and eject - */ - private OutlierConfig outlier; - - private Boolean localCacheEnabled; - - private Boolean storeLocalCacheAsync; - - /** - * for hairuo, 控制程序初始化阶段是否可以拉取服务列表 - */ - private Boolean fetchInstancesWhenInitEnabled; - - /** - * support interface level - */ - private Map interfaceConfig; - - public ClientConfig() { - this.interfaceConfig = new HashMap<>(); - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getCompressType() { - return compressType; - } - - public void setCompressType(String compressType) { - this.compressType = compressType; - } - - public String getFilters() { - return filters; - } - - public void setFilters(String filters) { - this.filters = filters; - } - - public String getClusterModel() { - return clusterModel; - } - - public void setClusterModel(String clusterModel) { - this.clusterModel = clusterModel; - } - - public Integer getWarmUpRatio() { - return warmUpRatio; - } - - public void setWarmUpRatio(Integer warmUpRatio) { - this.warmUpRatio = warmUpRatio; - } - - public Integer getWarmUpCount() { - return warmUpCount; - } - - public void setWarmUpCount(Integer warmUpCount) { - this.warmUpCount = warmUpCount; - } - - public Integer getConnectTimeoutMills() { - return connectTimeoutMills; - } - - public void setConnectTimeoutMills(Integer connectTimeoutMills) { - this.connectTimeoutMills = connectTimeoutMills; - } - - public Integer getWriteTimeoutMills() { - return writeTimeoutMills; - } - - public void setWriteTimeoutMills(Integer writeTimeoutMills) { - this.writeTimeoutMills = writeTimeoutMills; - } - - public Integer getReadIdleTimeout() { - return readIdleTimeout; - } - - public void setReadIdleTimeout(Integer readIdleTimeout) { - this.readIdleTimeout = readIdleTimeout; - } - - public Integer getMaxHeartbeatTimes() { - return maxHeartbeatTimes; - } - - public void setMaxHeartbeatTimes(Integer maxHeartbeatTimes) { - this.maxHeartbeatTimes = maxHeartbeatTimes; - } - - public Integer getIoThreadNum() { - return ioThreadNum; - } - - public void setIoThreadNum(Integer ioThreadNum) { - this.ioThreadNum = ioThreadNum; - } - - public String getChannelType() { - return channelType; - } - - public void setChannelType(String channelType) { - this.channelType = channelType; - } - - public Integer getMaxConnections() { - return maxConnections; - } - - public void setMaxConnections(Integer maxConnections) { - this.maxConnections = maxConnections; - } - - public Integer getMaxIdleConnections() { - return maxIdleConnections; - } - - public void setMaxIdleConnections(Integer maxIdleConnections) { - this.maxIdleConnections = maxIdleConnections; - } - - public Integer getMinIdleConnections() { - return minIdleConnections; - } - - public void setMinIdleConnections(Integer minIdleConnections) { - this.minIdleConnections = minIdleConnections; - } - - public Integer getRequestTimeoutMills() { - return requestTimeoutMills; - } - - public Integer getRequestTimeoutMills(String className) { - InterfaceConfig config = interfaceConfig.get(className); - if (config != null && config.getRequestTimeoutMills() != null) { - return config.getRequestTimeoutMills(); - } - - if (requestTimeoutMills != null) { - return requestTimeoutMills; - } - - return null; - } - - public void setRequestTimeoutMills(Integer requestTimeoutMills) { - this.requestTimeoutMills = requestTimeoutMills; - } - - public Integer getRetryTimes() { - return retryTimes; - } - - /** - * Get retry times for the specify interface - * - * @param className - * @return - */ - public Integer getRetryTimes(String className) { - InterfaceConfig config = interfaceConfig.get(className); - if (config != null && config.getRetryTimes() != null) { - return config.getRetryTimes(); - } - - if (retryTimes != null) { - return retryTimes; - } - - return null; - } - - public void setRetryTimes(Integer retryTimes) { - this.retryTimes = retryTimes; - } - - public String getRetryMethods() { - return retryMethods; - } - - /** - * Get retry methods for the specify interface - * - * @param className - * @return - */ - public String getRetryMethods(String className) { - InterfaceConfig config = interfaceConfig.get(className); - if (config != null && config.getRetryMethods() != null) { - return config.getRetryMethods(); - } - - if (retryMethods != null) { - return retryMethods; - } - - return null; - } - - public void setRetryMethods(String retryMethods) { - this.retryMethods = retryMethods; - } - - public Integer getRetryDelayTimeUnitMills() { - return retryDelayTimeUnitMills; - } - - /** - * Get retry retryDelayTimeUnitMills for the specify interface - * - * @param className - * @return - */ - public Integer getRetryDelayTimeUnitMills(String className) { - InterfaceConfig config = interfaceConfig.get(className); - if (config != null && config.getRetryDelayTimeUnitMills() != null) { - return config.getRetryDelayTimeUnitMills(); - } - - if (retryDelayTimeUnitMills != null) { - return retryDelayTimeUnitMills; - } - - return null; - } - - public void setRetryDelayTimeUnitMills(Integer retryDelayTimeUnitMills) { - this.retryDelayTimeUnitMills = retryDelayTimeUnitMills; - } - - public Map getInterfaceConfig() { - return interfaceConfig; - } - - public void setInterfaceConfig(Map interfaceConfig) { - this.interfaceConfig = interfaceConfig; - } - - public String getSerializeMode() { - return serializeMode; - } - - public void setSerializeMode(String serializeMode) { - this.serializeMode = serializeMode; - } - - public Boolean getConnectKeepAliveEnable() { - return connectKeepAliveEnable; - } - - public void setConnectKeepAliveEnable(Boolean connectKeepAliveEnable) { - this.connectKeepAliveEnable = connectKeepAliveEnable; - } - - public OutlierConfig getOutlier() { - return outlier; - } - - public void setOutlier(OutlierConfig outlier) { - this.outlier = outlier; - } - - public Integer getNetworkErrorRetryTimes() { - return networkErrorRetryTimes; - } - - public void setNetworkErrorRetryTimes(Integer networkErrorRetryTimes) { - this.networkErrorRetryTimes = networkErrorRetryTimes; - } - - public Boolean getLocalCacheEnabled() { - return localCacheEnabled; - } - - public void setLocalCacheEnabled(Boolean localCacheEnabled) { - this.localCacheEnabled = localCacheEnabled; - } - - public Boolean getStoreLocalCacheAsync() { - return storeLocalCacheAsync; - } - - public void setStoreLocalCacheAsync(Boolean storeLocalCacheAsync) { - this.storeLocalCacheAsync = storeLocalCacheAsync; - } - - public Boolean getFetchInstancesWhenInitEnabled() { - return fetchInstancesWhenInitEnabled; - } - - public void setFetchInstancesWhenInitEnabled(Boolean fetchInstancesWhenInitEnabled) { - this.fetchInstancesWhenInitEnabled = fetchInstancesWhenInitEnabled; - } - - public Boolean getWarmUpEnabled() { - return warmUpEnabled; - } - - public void setWarmUpEnabled(Boolean warmUpEnabled) { - this.warmUpEnabled = warmUpEnabled; - } - - public String getRetryErrorCodes() { - return retryErrorCodes; - } - - /** - * Get retry methods for the specify interface - * - * @param className - * @return - */ - public String getRetryErrorCodes(String className) { - InterfaceConfig config = interfaceConfig.get(className); - if (config != null && config.getRetryErrorCodes() != null) { - return config.getRetryErrorCodes(); - } - - if (retryErrorCodes != null) { - return retryErrorCodes; - } - - return null; - } - - public void setRetryErrorCodes(String retryErrorCodes) { - this.retryErrorCodes = retryErrorCodes; - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/InterfaceConfig.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/InterfaceConfig.java deleted file mode 100644 index 7afd2a08..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/InterfaceConfig.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -/** - * Support interface level config Created by liuruisen on 2020/12/10. - */ -public class InterfaceConfig { - - private Integer requestTimeoutMills; - - private Integer retryTimes; // interface level - - private String retryMethods; // interface level - - /** - * The time unit of the time interval between two retries, which will be used to calculate the true delay time. - */ - private Integer retryDelayTimeUnitMills; // default 100; interface level - - private String retryErrorCodes; // split by , default null - - public Integer getRequestTimeoutMills() { - return requestTimeoutMills; - } - - public void setRequestTimeoutMills(Integer requestTimeoutMills) { - this.requestTimeoutMills = requestTimeoutMills; - } - - public Integer getRetryTimes() { - return retryTimes; - } - - public void setRetryTimes(Integer retryTimes) { - this.retryTimes = retryTimes; - } - - public String getRetryMethods() { - return retryMethods; - } - - public void setRetryMethods(String retryMethods) { - this.retryMethods = retryMethods; - } - - public Integer getRetryDelayTimeUnitMills() { - return retryDelayTimeUnitMills; - } - - public void setRetryDelayTimeUnitMills(Integer retryDelayTimeUnitMills) { - this.retryDelayTimeUnitMills = retryDelayTimeUnitMills; - } - - public String getRetryErrorCodes() { - return retryErrorCodes; - } - - public void setRetryErrorCodes(String retryErrorCodes) { - this.retryErrorCodes = retryErrorCodes; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfig.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfig.java deleted file mode 100644 index 7b778b93..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfig.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import java.lang.reflect.Field; - -/** - * Created by liuruisen on 2021/4/22. - */ -public class OutlierConfig { - - private Boolean enabled; - - private Integer detectInterval; - - private Integer failurePercentMinRequest; - - private Integer failurePercentThreshold; - - private Integer failureCountThreshold; - - private Integer baseEjectTime; - - private Integer maxEjectTime; - - private Integer maxEjectPercent; - - // 是否启用离线检测恢复,false将不进行心跳检测恢复 - private Boolean recoverByCheckEnabled; - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public Integer getDetectInterval() { - return detectInterval; - } - - public void setDetectInterval(Integer detectInterval) { - this.detectInterval = detectInterval; - } - - public Integer getFailurePercentMinRequest() { - return failurePercentMinRequest; - } - - public void setFailurePercentMinRequest(Integer failurePercentMinRequest) { - this.failurePercentMinRequest = failurePercentMinRequest; - } - - public Integer getFailurePercentThreshold() { - return failurePercentThreshold; - } - - public void setFailurePercentThreshold(Integer failurePercentThreshold) { - this.failurePercentThreshold = failurePercentThreshold; - } - - public Integer getBaseEjectTime() { - return baseEjectTime; - } - - public void setBaseEjectTime(Integer baseEjectTime) { - this.baseEjectTime = baseEjectTime; - } - - public Integer getMaxEjectTime() { - return maxEjectTime; - } - - public void setMaxEjectTime(Integer maxEjectTime) { - this.maxEjectTime = maxEjectTime; - } - - public Integer getMaxEjectPercent() { - return maxEjectPercent; - } - - public void setMaxEjectPercent(Integer maxEjectPercent) { - this.maxEjectPercent = maxEjectPercent; - } - - public Integer getFailureCountThreshold() { - return failureCountThreshold; - } - - public void setFailureCountThreshold(Integer failureCountThreshold) { - this.failureCountThreshold = failureCountThreshold; - } - - public Boolean getRecoverByCheckEnabled() { - return recoverByCheckEnabled; - } - - public void setRecoverByCheckEnabled(Boolean recoverByCheckEnabled) { - this.recoverByCheckEnabled = recoverByCheckEnabled; - } - - /** - * 合并,传入对象优先级高 - * - * @param outlierConfig - */ - public void merge(OutlierConfig outlierConfig) { - if (outlierConfig == null) { - return; - } - try { - for (Field field : this.getClass().getDeclaredFields()) { - field.setAccessible(true); - if (field.get(outlierConfig) != null) { - field.set(this, field.get(outlierConfig)); - } - } - } catch (IllegalAccessException e) { - // ignore - throw new RuntimeException(e); - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientProperties.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientProperties.java deleted file mode 100644 index e4131c13..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientProperties.java +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.HashMap; -import java.util.Map; - -/** - * Global configuration for all RpcProxies Created by liuruisen on 2019-07-10. - */ -@ConfigurationProperties(prefix = StarlightClientProperties.PREFIX) -public class StarlightClientProperties { - - static final String PREFIX = "starlight.client"; - - private String defaultConfig = "default"; // global level - - private Integer bizThreadNum; // global - - private Integer ioRatio; // global, netty ioRatio default 100 - - private Map config; // support application level - - public Map getConfig() { - return config; - } - - public void setConfig(Map config) { - this.config = config; - } - - public ClientConfig getClientConfig(String clientName) { - return config.get(clientName); - } - - public String getDefaultConfig() { - return defaultConfig; - } - - public Integer getBizThreadNum() { - return bizThreadNum; - } - - public void setBizThreadNum(Integer bizThreadNum) { - this.bizThreadNum = bizThreadNum; - } - - public Integer getIoRatio() { - return ioRatio; - } - - public void setIoRatio(Integer ioRatio) { - this.ioRatio = ioRatio; - } - - public StarlightClientProperties() { - this.config = new HashMap<>(); - config.putIfAbsent(defaultConfig, new ClientConfig()); - } - - public TransportConfig transportConfig(String name) { - TransportConfig transportConfig = new TransportConfig(); - // config default - transportConfig.setIoThreadNum(getIoThreadNum(name)); - transportConfig.setConnectTimeoutMills(getConnectTimeoutMills(name)); - transportConfig.setMaxHeartbeatTimes(getMaxHeartbeatTimes(name)); - transportConfig.setWriteTimeoutMills(getWriteTimeoutMills(name)); - transportConfig.setReadIdleTimeout(getReadIdleTimeout(name)); - transportConfig.setRequestTimeoutMills(getRequestTimeoutMills(name)); - - // channel info - transportConfig.setChannelType(getChannelType(name)); - transportConfig.setMaxConnections(getMaxConnections(name)); - transportConfig.setMaxIdleConnections(getMaxIdleConnections(name)); - transportConfig.setMinIdleConnections(getMinIdleConnections(name)); - transportConfig.setConnectKeepAliveEnable(getConnectKeepAliveEnable(name)); - - transportConfig.setBizWorkThreadNum(this.bizThreadNum); - transportConfig.setIoRatio(this.ioRatio); - - return transportConfig; - } - - public Integer getIoThreadNum(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getIoThreadNum() != null) { - return clientConfig.getIoThreadNum(); - } - - if (globalConfig != null && globalConfig.getIoThreadNum() != null) { - return globalConfig.getIoThreadNum(); - } - - return Constants.DEFAULT_IO_THREADS_VALUE; - } - - public Integer getConnectTimeoutMills(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getConnectTimeoutMills() != null) { - return clientConfig.getConnectTimeoutMills(); - } - - if (globalConfig != null && globalConfig.getConnectTimeoutMills() != null) { - return globalConfig.getConnectTimeoutMills(); - } - - return Constants.CONNECT_TIMEOUT_VALUE; - } - - public Integer getMaxHeartbeatTimes(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getMaxHeartbeatTimes() != null) { - return clientConfig.getMaxHeartbeatTimes(); - } - - if (globalConfig != null && globalConfig.getMaxHeartbeatTimes() != null) { - return globalConfig.getMaxHeartbeatTimes(); - } - - return Constants.MAX_HEARTBEAT_TIMES_VALUE; - } - - public Integer getWriteTimeoutMills(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getWriteTimeoutMills() != null) { - return clientConfig.getWriteTimeoutMills(); - } - - if (globalConfig != null && globalConfig.getWriteTimeoutMills() != null) { - return globalConfig.getWriteTimeoutMills(); - } - - return Constants.WRITE_TIMEOUT_VALUE; - } - - public Integer getReadIdleTimeout(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getReadIdleTimeout() != null) { - return clientConfig.getReadIdleTimeout(); - } - - if (globalConfig != null && globalConfig.getReadIdleTimeout() != null) { - return globalConfig.getReadIdleTimeout(); - } - - return Constants.READ_IDLE_TIMEOUT_VALUE; - } - - public Integer getRequestTimeoutMills(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getRequestTimeoutMills() != null) { - return clientConfig.getRequestTimeoutMills(); - } - - if (globalConfig != null && globalConfig.getRequestTimeoutMills() != null) { - return globalConfig.getRequestTimeoutMills(); - } - - return Constants.REQUEST_TIMEOUT_VALUE; - } - - public Integer getRequestTimeoutMills(String clientName, String className) { - ClientConfig clientConfig = config.get(clientName); - if (clientConfig != null && clientConfig.getRequestTimeoutMills(className) != null) { - return clientConfig.getRequestTimeoutMills(className); - } - - ClientConfig globalConfig = config.get(defaultConfig); - if (globalConfig != null && globalConfig.getRequestTimeoutMills(className) != null) { - return globalConfig.getRequestTimeoutMills(className); - } - - return Constants.REQUEST_TIMEOUT_VALUE; - } - - public Integer getWarmUpRatio(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getWarmUpRatio() != null) { - return clientConfig.getWarmUpRatio(); - } - - if (globalConfig != null && globalConfig.getWarmUpRatio() != null) { - return globalConfig.getWarmUpRatio(); - } - - return SpringCloudConstants.DEFAULT_WARM_UP_RATIO; - } - - public Integer getWarmUpCount(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getWarmUpCount() != null) { - return clientConfig.getWarmUpCount(); - } - - if (globalConfig != null && globalConfig.getWarmUpCount() != null) { - return globalConfig.getWarmUpCount(); - } - - return null; - } - - public String getChannelType(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getChannelType() != null) { - return clientConfig.getChannelType(); - } - - if (globalConfig != null && globalConfig.getChannelType() != null) { - return globalConfig.getChannelType(); - } - - return Constants.DEFAULT_RPC_CHANNEL_TYPE_VALUE; - } - - public String getClusterModel(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getClusterModel() != null) { - return clientConfig.getClusterModel(); - } - - if (globalConfig != null && globalConfig.getClusterModel() != null) { - return globalConfig.getClusterModel(); - } - - return SpringCloudConstants.DEFAULT_CLUSTER_MODEL; - } - - public Integer getMaxConnections(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getMaxConnections() != null) { - return clientConfig.getMaxConnections(); - } - - if (globalConfig != null && globalConfig.getMaxConnections() != null) { - return globalConfig.getMaxConnections(); - } - - return Constants.MAX_TOTAL_CONNECTIONS; - } - - public Integer getMaxIdleConnections(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getMaxIdleConnections() != null) { - return clientConfig.getMaxIdleConnections(); - } - - if (globalConfig != null && globalConfig.getMaxIdleConnections() != null) { - return globalConfig.getMaxIdleConnections(); - } - - return Constants.MAX_IDLE_CONNECTIONS; - } - - public Integer getMinIdleConnections(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getMinIdleConnections() != null) { - return clientConfig.getMinIdleConnections(); - } - - if (globalConfig != null && globalConfig.getMinIdleConnections() != null) { - return globalConfig.getMinIdleConnections(); - } - - return Constants.MIN_IDLE_CONNECTIONS; - } - - public String getProtocol(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getProtocol() != null) { - return clientConfig.getProtocol(); - } - - if (globalConfig != null && globalConfig.getProtocol() != null) { - return globalConfig.getProtocol(); - } - - return null; // protocol select logic will select a protocol - } - - public String getCompressType(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getCompressType() != null) { - return clientConfig.getCompressType(); - } - - if (globalConfig != null && globalConfig.getCompressType() != null) { - return globalConfig.getCompressType(); - } - - return Constants.COMPRESS_TYPE; - } - - public String getFilters(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getFilters() != null) { - return SpringCloudConstants.DEFAULT_CLIENT_FILTERS + Constants.FILTER_NAME_SPLIT_KEY - + clientConfig.getFilters(); - } - - if (globalConfig != null && globalConfig.getFilters() != null) { - return SpringCloudConstants.DEFAULT_CLIENT_FILTERS + Constants.FILTER_NAME_SPLIT_KEY - + globalConfig.getFilters(); - } - - return SpringCloudConstants.DEFAULT_CLIENT_FILTERS; - } - - public Integer getRetryTimes(String clientName, String className) { - ClientConfig clientConfig = config.get(clientName); - if (clientConfig != null && clientConfig.getRetryTimes(className) != null) { - return clientConfig.getRetryTimes(className); - } - - ClientConfig globalConfig = config.get(defaultConfig); - if (globalConfig != null && globalConfig.getRetryTimes(className) != null) { - return globalConfig.getRetryTimes(className); - } - - return SpringCloudConstants.DEFAULT_RETRY_TIMES; - } - - public Integer getRetryDelayTimeUnitMills(String clientName, String className) { - ClientConfig clientConfig = config.get(clientName); - if (clientConfig != null && clientConfig.getRetryDelayTimeUnitMills(className) != null) { - return clientConfig.getRetryDelayTimeUnitMills(className); - } - - ClientConfig globalConfig = config.get(defaultConfig); - if (globalConfig != null && globalConfig.getRetryDelayTimeUnitMills(className) != null) { - return globalConfig.getRetryDelayTimeUnitMills(className); - } - - return SpringCloudConstants.DEFAULT_RETRY_DELAY_MILLS; - } - - public String getRetryMethods(String clientName, String className) { - ClientConfig clientConfig = config.get(clientName); - if (clientConfig != null && clientConfig.getRetryMethods(className) != null) { - return clientConfig.getRetryMethods(className); - } - - ClientConfig globalConfig = config.get(defaultConfig); - if (globalConfig != null && globalConfig.getRetryMethods(className) != null) { - return globalConfig.getRetryMethods(className); - } - - return null; - } - - public String getRetryErrorCodes(String clientName, String className) { - ClientConfig clientConfig = config.get(clientName); - if (clientConfig != null && clientConfig.getRetryErrorCodes(className) != null) { - return clientConfig.getRetryErrorCodes(className); - } - - ClientConfig globalConfig = config.get(defaultConfig); - if (globalConfig != null && globalConfig.getRetryErrorCodes(className) != null) { - return globalConfig.getRetryErrorCodes(className); - } - - return null; - } - - public String getSerializeMode(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getSerializeMode() != null) { - return clientConfig.getSerializeMode(); - } - - if (globalConfig != null && globalConfig.getSerializeMode() != null) { - return globalConfig.getSerializeMode(); - } - - return Constants.PROTO2_STD_MODE; // default is proto2 std: proto2-std - } - - public Boolean getConnectKeepAliveEnable(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getConnectKeepAliveEnable() != null) { - return clientConfig.getConnectKeepAliveEnable(); - } - - if (globalConfig != null && globalConfig.getConnectKeepAliveEnable() != null) { - return globalConfig.getConnectKeepAliveEnable(); - } - - return Constants.CONNECT_KEEPALIVE_ENABLED_VALUE; // default is false - } - - /** - * Get outlier config for the specificed client - * - * @param clientName - * @return - */ - public OutlierConfig getOutlierConfig(String clientName) { - OutlierConfig outlierConfig = new OutlierConfig(); - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - OutlierConfig globalOutlierConfig = null; - if (globalConfig != null && globalConfig.getOutlier() != null) { - globalOutlierConfig = globalConfig.getOutlier(); - } - // default > new - outlierConfig.merge(globalOutlierConfig); - - OutlierConfig clientOutlierConfig = null; - if (clientConfig != null && clientConfig.getOutlier() != null) { - clientOutlierConfig = clientConfig.getOutlier(); - } - - // client > default - outlierConfig.merge(clientOutlierConfig); - - // set default value if the value is null - if (outlierConfig.getEnabled() == null) { - outlierConfig.setEnabled(SpringCloudConstants.OUTLIER_DETECT_ENABLED); // false - } - - if (outlierConfig.getDetectInterval() == null) { - // 30 - outlierConfig.setDetectInterval(SpringCloudConstants.OUTLIER_DETECT_INTERVAL); - } - - if (outlierConfig.getFailurePercentMinRequest() == null) { - // 5 - outlierConfig.setFailurePercentMinRequest(SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM); - } - - if (outlierConfig.getFailurePercentThreshold() == null) { - // 20% - outlierConfig.setFailurePercentThreshold(SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD); - } - - if (outlierConfig.getBaseEjectTime() == null) { - // 30s - outlierConfig.setBaseEjectTime(SpringCloudConstants.OUTLIER_DETECT_BASE_EJECT_TIME); - } - - if (outlierConfig.getMaxEjectTime() == null) { - // 300s - outlierConfig.setMaxEjectTime(SpringCloudConstants.OUTLIER_DETECT_MAX_EJECT_TIME); - } - - if (outlierConfig.getMaxEjectPercent() == null) { - // 20% - outlierConfig.setMaxEjectPercent(SpringCloudConstants.OUTLIER_DETECT_MAX_EJECT_PERCENT); - } - - if (outlierConfig.getRecoverByCheckEnabled() == null) { - // true - outlierConfig.setRecoverByCheckEnabled(SpringCloudConstants.OUTLIER_RECOVER_BY_CHECK_ENABLED); - } - - return outlierConfig; - } - - public Integer getNetworkErrorRetryTimes(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getNetworkErrorRetryTimes() != null) { - return clientConfig.getNetworkErrorRetryTimes(); - } - - if (globalConfig != null && globalConfig.getNetworkErrorRetryTimes() != null) { - return globalConfig.getNetworkErrorRetryTimes(); - } - - return SpringCloudConstants.NETWORK_ERROR_RETRY_TIMES; // default is 3 - } - - public Boolean getLocalCacheEnabled(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getLocalCacheEnabled() != null) { - return clientConfig.getLocalCacheEnabled(); - } - - if (globalConfig != null && globalConfig.getLocalCacheEnabled() != null) { - return globalConfig.getLocalCacheEnabled(); - } - - return SpringCloudConstants.LOCAL_CACHE_ENABLED; // default value is true - } - - public Boolean getStoreLocalCacheAsync(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getStoreLocalCacheAsync() != null) { - return clientConfig.getStoreLocalCacheAsync(); - } - - if (globalConfig != null && globalConfig.getStoreLocalCacheAsync() != null) { - return globalConfig.getStoreLocalCacheAsync(); - } - - return SpringCloudConstants.STORE_LOCAL_CACHE_ASYNC; // default value is false - } - - public Boolean getFetchInstancesWhenInitEnabled(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getFetchInstancesWhenInitEnabled() != null) { - return clientConfig.getFetchInstancesWhenInitEnabled(); - } - - if (globalConfig != null && globalConfig.getFetchInstancesWhenInitEnabled() != null) { - return globalConfig.getFetchInstancesWhenInitEnabled(); - } - - return true; // default value is true - } - - public Boolean getWarmUpEnabled(String clientName) { - ClientConfig globalConfig = config.get(defaultConfig); - ClientConfig clientConfig = config.get(clientName); - - if (clientConfig != null && clientConfig.getWarmUpEnabled() != null) { - return clientConfig.getWarmUpEnabled(); - } - - if (globalConfig != null && globalConfig.getWarmUpEnabled() != null) { - return globalConfig.getWarmUpEnabled(); - } - - return true; // default value is true - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightRouteProperties.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightRouteProperties.java deleted file mode 100644 index 34affcea..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightRouteProperties.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Created by liuruisen on 2021/12/7. - */ -@ConfigurationProperties(prefix = StarlightRouteProperties.PREFIX) -public class StarlightRouteProperties { - - static final String PREFIX = "starlight.client.route"; - - private final Map labelSelectorCache = new ConcurrentHashMap<>(); - - private Boolean enabled = true; - - private Boolean noInstanceFallBack = true; // 匹配到路由规则,未发现服务列表时,是否降级 - - /** - * label selector 静态配置,实现gravity label selector能力 - */ - private Selector labelSelector = new Selector(); - - /** - * serviceId名称映射,跨注册中心场景下的内容路由支持 1. bns服务发现场景下的内容路由,key:bns value:应用名 - */ - private Map serviceIdMap = new HashMap<>(); - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public Selector getLabelSelector() { - return labelSelector; - } - - public void setLabelSelector(Selector labelSelector) { - this.labelSelector = labelSelector; - } - - public Boolean getNoInstanceFallBack() { - return noInstanceFallBack; - } - - public void setNoInstanceFallBack(Boolean noInstanceFallBack) { - this.noInstanceFallBack = noInstanceFallBack; - } - - public Map getServiceIdMap() { - return serviceIdMap; - } - - public void setServiceIdMap(Map serviceIdMap) { - this.serviceIdMap = serviceIdMap; - } - - public static class Selector { - /** - * Label selector configs for each service id. - *

- * For example, if you want to find only instances of service "hello_service" which match version 2.0.0 and - * located at "nj02" region. - *

- * spring.cloud.gravity: discovery: provider-selector: hello_service: version=2.0.0 && region=nj02 - *

- * or - *

- * starlight.client.route: selector: provider-selector: hello_service: version=2.0.0 && region=nj02 - *

- * A label selector is an expression combined only by "&&" semantic separator. Each part of the expression is - * composed by label + operator + value. Operators "=", "!=", are supported for single value expression, such as - * `version=2.0.0`, `region != nj02`. And operators "in", "not in" are supported for set/collection value - * expression, such as `region in (nj02, bj01)`. - */ - private Map providerSelector; - - /** - * Global label selector applied for all service ids Selector keys in globalSelector has lower priority than - * providerSelector - */ - private String globalSelector; - - /** - * providerSelector can be disable when enableProviderSelector is false - */ - private Boolean enableProviderSelector; - - public Map getProviderSelector() { - return providerSelector; - } - - public void setProviderSelector(Map providerSelector) { - this.providerSelector = providerSelector; - } - - public String getGlobalSelector() { - return globalSelector; - } - - public void setGlobalSelector(String globalSelector) { - this.globalSelector = globalSelector; - } - - public Boolean getEnableProviderSelector() { - return enableProviderSelector; - } - - public void setEnableProviderSelector(boolean enableProviderSelector) { - this.enableProviderSelector = enableProviderSelector; - } - } - - /** - * Get label selector for service id - * - * @param serviceId service id - * @return label selector (string), will never return null - */ - public String getServiceLabelSelector(String serviceId) { - String selector = labelSelectorCache.computeIfAbsent(serviceId, k -> { - String labelSelector = ""; - if (this.labelSelector.getEnableProviderSelector() == null - || !this.labelSelector.getEnableProviderSelector()) { - labelSelector = this.labelSelector.globalSelector; - } else { - labelSelector = mergeSelector(this.labelSelector.globalSelector, - this.labelSelector.providerSelector.get(serviceId)); - } - return labelSelector; - }); - - return selector; - } - - public String mergeSelector(String globalSelector, String selector) { - if (StringUtils.isBlank(selector)) { - return globalSelector; - } - if (StringUtils.isBlank(globalSelector)) { - return selector; - } - Set uniqueKeys = new HashSet<>(); - return Stream.of(selector, globalSelector).map(this::splitSelectorsByKey).flatMap(Collection::stream).map(x -> { - if (!uniqueKeys.contains(x[0])) { - uniqueKeys.add(x[0]); - return x[1]; - } else { - return null; - } - }).filter(Objects::nonNull).collect(Collectors.joining(" && ")); - } - - private List splitSelectorsByKey(String selector) { - return Stream.of(selector.split("&&")).map(String::trim).filter(StringUtils::isNotBlank).map(x -> { - for (String splitter : new String[] {" not in ", " in ", "!=", "="}) { - int i = x.indexOf(splitter); - if (i != -1) { - return new String[] {x.substring(0, i).trim(), x}; - } - } - return null; - }).filter(Objects::nonNull).collect(Collectors.toList()); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilter.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilter.java deleted file mode 100644 index 65309cf7..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilter.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.shutdown; - -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.StarlightServerListFilter; -import com.baidu.cloud.starlight.springcloud.common.InstanceUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * Remove shutdown instance filter - *

- * Created by liuruisen on 2021/4/23. - */ -public class ShutdownServerListFilter implements StarlightServerListFilter { - - /** - * 30 min - */ - private static final Integer SHUTDOWN_CLEAN_UP_PERIOD = 30 * 60 * 1000; - - private final SingleStarlightClientManager clientManager; - - private final StarlightClientProperties clientProperties; - - private final Map shutdownCleanTasks; - - public ShutdownServerListFilter(SingleStarlightClientManager clientManager, - StarlightClientProperties clientProperties) { - this.clientManager = clientManager; - this.clientProperties = clientProperties; - this.shutdownCleanTasks = new ConcurrentHashMap<>(); - } - - @Override - public List getFilteredList(List originServers) { - - long filterStartTime = System.currentTimeMillis(); - - if (originServers == null || originServers.isEmpty()) { - return originServers; - } - - // Since the original servers is unmodifiable, we copy once - List serverList = new LinkedList<>(originServers); - - for (ServiceInstance server : originServers) { - Map serverMetas = server.getMetadata(); - - if (serverMetas != null && serverMetas.size() > 0) { - - SingleStarlightClient starlightClient = - clientManager.getSingleClient(server.getHost(), server.getPort()); - // starlight client is null, this client is not used in a long period - // have the right to be selected by load balancing - if (starlightClient == null) { - continue; - } - - // epoch empty continue - String epoch = serverMetas.get(SpringCloudConstants.EPOCH_KEY); - if (StringUtils.isEmpty(epoch)) { - LOGGER.debug("The server discovered by registry does not have EPOCH meta!"); - continue; - } - - long epochTime = Long.parseLong(epoch); - - // peer status null, continue - PeerStatus peerStatus = starlightClient.getStatus(); - if (peerStatus == null) { - continue; - } - - // epoch > in active time, the server is reboot - - // starlight client is not shutdown, have the right to be selected by load balancing - if (!PeerStatus.Status.SHUTTING_DOWN.equals(peerStatus.getStatus()) - && !PeerStatus.Status.SHUTDOWN.equals(peerStatus.getStatus())) { - continue; - } - long shutdownTime = peerStatus.getStatusRecordTime(); - - // The service is inactive and has no right to be selected by the load balancer - if (epochTime < shutdownTime) { - serverList.remove(server); - LOGGER.info("Remote server {} had been removed because of shutdown, shutdownTime {}.", - InstanceUtils.ipPortStr(server), peerStatus.getStatusRecordTime()); - submitTimerTask(server, SHUTDOWN_CLEAN_UP_PERIOD); - } - } - } - LOGGER.debug("ShutdownServerListFilter getFilteredList cost {}", System.currentTimeMillis() - filterStartTime); - - return serverList; - } - - @Override - public Map getServerListFilterTasks() { - return this.shutdownCleanTasks; - } - - @Override - public SingleStarlightClientManager getSingleClientManager() { - return this.clientManager; - } - - @Override - public int getOrder() { - return SpringCloudConstants.SHUTTING_DOWN_SERVER_LIST_FILTER_ORDER; - } - - @Override - public void submitTimerTask(ServiceInstance server, Integer execDelay) { - if (shutdownCleanTasks.get(InstanceUtils.ipPortStr(server)) != null) { - return; - } - Timeout timeout = - SERVER_LIST_FILTER_TIMER.newTimeout(new ShutdownInstanceCleanTask(server), execDelay, TimeUnit.SECONDS); - shutdownCleanTasks.put(InstanceUtils.ipPortStr(server), timeout); - } - - @Override - public void destroy() { - if (shutdownCleanTasks.size() > 0) { - for (Map.Entry task : shutdownCleanTasks.entrySet()) { - if (task != null && task.getValue() != null) { - task.getValue().cancel(); - } - } - } - } - - private class ShutdownInstanceCleanTask implements TimerTask { - - private final ServiceInstance server; - - public ShutdownInstanceCleanTask(ServiceInstance server) { - this.server = server; - } - - @Override - public void run(Timeout timeout) throws Exception { - SingleStarlightClient singleClient = clientManager.getSingleClient(server.getHost(), server.getPort()); - if (singleClient == null) { - return; - } - - PeerStatus peerStatus = singleClient.getStatus(); - if (peerStatus == null) { - return; - } - - if (!PeerStatus.Status.SHUTTING_DOWN.equals(peerStatus.getStatus()) - || !PeerStatus.Status.SHUTDOWN.equals(peerStatus.getStatus())) { - return; - } - - if ((System.currentTimeMillis() - peerStatus.getStatusRecordTime()) >= SHUTDOWN_CLEAN_UP_PERIOD) { - StarlightStatsManager.removeStats(singleClient.remoteURI()); - clientManager.removeSingleClient(server.getHost(), server.getPort()); - } - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtils.java deleted file mode 100644 index 8b3581ad..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtils.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -/** - * Created by liuruisen on 2020/3/5. - */ -public class ApplicationContextUtils implements ApplicationContextAware { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContextUtils.class); - - private static final String[] WEB_ENVIRONMENT_CLASSES = - {"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"}; - - private static ApplicationContext applicationContext; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - /** - * Get Bean - * - * @param tClass - * @param - * @return - */ - public static T getBeanByType(Class tClass) { - if (tClass == null) { - return null; - } - return applicationContext.getBean(tClass); - } - - /** - * Get application context - * - * @return - */ - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - /** - * Get Environment - * - * @return - */ - public static Environment getEnvironment() { - return applicationContext.getEnvironment(); - } - - public static boolean isJarvisEnv() { - String emProductLine = System.getenv(SpringCloudConstants.EM_PRODUCT_LINE); - String emPlatform = System.getenv(SpringCloudConstants.EM_PLATFORM); - String emApp = System.getenv(SpringCloudConstants.EM_APP); - - return !StringUtils.isEmpty(emProductLine) && !StringUtils.isEmpty(emPlatform) && !StringUtils.isEmpty(emApp); - } - - public static boolean deduceWebEnvironment() { - for (String className : WEB_ENVIRONMENT_CLASSES) { - if (!ClassUtils.isPresent(className, null)) { - return false; - } - } - if (getEnvironment().getProperty("spring.main.web-application-type") != null - && getEnvironment().getProperty("spring.main.web-application-type").equalsIgnoreCase("none")) { - return false; - } - - if (getApplicationContext() instanceof AnnotationConfigApplicationContext) { - return false; - } - return true; - } - - /** - * Get starlight port - * - * @return - */ - public static Integer getServerPort() { - StarlightServerProperties starlightServerProperties = getBeanByType(StarlightServerProperties.class); - - Integer port = starlightServerProperties.getPort(); - - if ((port == null || port <= 0) && !deduceWebEnvironment()) { - port = Integer.parseInt(getEnvironment().getProperty(SpringCloudConstants.SERVER_PORT_KEY, "8080").trim()); - } - - if (port == null || port <= 0) { - throw new IllegalArgumentException("The following two properties are all illegal, please check: " + "{" - + SpringCloudConstants.STARLIGHT_SERVER_PORT_KEY + "} " + "{" + SpringCloudConstants.SERVER_PORT_KEY - + "}"); - } - return port; - } - - /** - * Get application name from environment or env variable - * - * @return - */ - public static String getApplicationName() { - // Priority order: starlight.server.name > EM_APP(Jarvis) > spring.application.name - - // starlight.server.name - String appName = getEnvironment().getProperty(SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY); - - // EM_APP - if (StringUtils.isEmpty(appName) && ApplicationContextUtils.isJarvisEnv()) { - // if is jarvis platform, application name will be EM_APP - appName = System.getenv(SpringCloudConstants.EM_APP); - } - - // spring.application.name - if (StringUtils.isEmpty(appName)) { - appName = getEnvironment().getProperty(SpringCloudConstants.SPRING_APPLICATION_NAME_KEY); - } - - // default value "application" - if (StringUtils.isEmpty(appName)) { - LOGGER.warn( - "The following three properties are all empty : " + "{" + SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY - + "} " + "{" + SpringCloudConstants.SPRING_APPLICATION_NAME_KEY + "}" + "{" - + SpringCloudConstants.EM_APP + "}, will use default value {application}"); - - appName = "application"; - } - - return appName; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClassPresentUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClassPresentUtils.java deleted file mode 100644 index 8ee7a1ec..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClassPresentUtils.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import org.springframework.util.ClassUtils; - -/** - * Created by liuruisen on 2021/10/21. - */ -public class ClassPresentUtils { - - private static final String GRAVITY_DISCOVERY_SERVER_CLASS = - "com.baidu.cloud.gravity.discovery.discovery.ribbon.GravityDiscoveryServer"; - - private static final boolean GRAVITY_DISCOVERY_SERVER_PRESENT = - ClassUtils.isPresent(GRAVITY_DISCOVERY_SERVER_CLASS, ClassPresentUtils.class.getClassLoader()); - - private static final String CONSUL_SERVER_CLASS = "org.springframework.cloud.consul.discovery.ConsulServer"; - - private static final boolean CONSUL_SERVER_CLASS_PRESENT = - ClassUtils.isPresent(CONSUL_SERVER_CLASS, ClassPresentUtils.class.getClassLoader()); - - public static boolean isGravityServerPresent() { - return GRAVITY_DISCOVERY_SERVER_PRESENT; - } - - public static boolean isConsulServerPresent() { - return CONSUL_SERVER_CLASS_PRESENT; - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClusterLogUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClusterLogUtils.java deleted file mode 100644 index 01ca2d95..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ClusterLogUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.springcloud.client.outlier.OutlierDetectEvent; -import org.slf4j.Logger; -import org.springframework.cloud.client.ServiceInstance; - -/** - * Created by liuruisen on 2021/9/7. - */ -public class ClusterLogUtils { - - public static void logOutlierInstanceEject(Logger logger, String clientName, ServiceInstance serverInstance, - PeerStatus status) { - String outlierReason = "unknow"; - if (status.getStatusReason() instanceof OutlierDetectEvent) { - outlierReason = ((OutlierDetectEvent) status.getStatusReason()).outlierReason(); - } - logger.info("[OUTLIER] Outlier instance eject: " + "remoteName {}, instance {}, outlierTime {}, reason {}", - clientName, serverInstance.getHost() + ":" + serverInstance.getPort(), status.getStatusRecordTime(), - outlierReason); - } - - public static void logOutlierAppEject(Logger logger, String clientName, Integer originSize, Integer ejectCount, - Integer maxEjectCount) { - logger.info("[OUTLIER] Outlier app eject: remoteName {}, instanceNum {}, " + "ejectNum {}, maxEjectNum {}", - clientName, originSize, ejectCount, maxEjectCount); - } - - public static void logOutlierRecoverySucc(Logger logger, String clientName, ServiceInstance serviceInstance, - String recoveryReason, Integer lastEjectTime) { - logger.info("[OUTLIER] Outlier recover succ: remoteName {}, instance {}, reason {}, lastEjectTime {}s", - clientName, serviceInstance.getHost() + ":" + serviceInstance.getPort(), recoveryReason, lastEjectTime); - } - - public static void logOutlierRecoveryFail(Logger logger, String clientName, ServiceInstance serverInstance, - String failReason, Integer lastEjectTime, Integer nextEjectTime) { - logger.info( - "[OUTLIER] Outlier recover fail: remoteName {}, instance {}, reason {}, " - + "lastEjectTime {}s, nextEjectTime {}s", - clientName, serverInstance.getHost() + ":" + serverInstance.getPort(), failReason, lastEjectTime, - nextEjectTime); - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ConstantUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ConstantUtils.java deleted file mode 100644 index 23e43cda..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/ConstantUtils.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -public class ConstantUtils { - - public static final String STARLIGHT_NETTY_SERVER_FACTORY = "starlightNettyServerFactory"; - - public static final String STARLIGHT_NETTY_CLIENT_FACTORY = "starlightNettyClientFactory"; - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/InstanceUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/InstanceUtils.java deleted file mode 100644 index bd7981d8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/InstanceUtils.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.util.StringUtils; - -/** - * Created by liuruisen on 2020/12/2. - */ -public class InstanceUtils { - - public static String ipPortStr(String host, Integer port) { - return String.format("%s:%d", host, port); - } - - public static String ipPortStr(ServiceInstance serviceInstance) { - return ipPortStr(serviceInstance.getHost(), serviceInstance.getPort()); - } - - /** - * 是否是bns实例 - * - * @param serviceId - * @return - */ - public static boolean isBnsServiceId(String serviceId) { - if (StringUtils.isEmpty(serviceId)) { - return false; - } - - String[] parts = serviceId.split("\\."); - return parts.length == 4; - } - - /** - * 是否是gravity实例 - * - * @param serviceId - * @return - */ - public static boolean isGravityServiceId(String serviceId) { - if (StringUtils.isEmpty(serviceId)) { - return false; - } - - String[] parts = serviceId.split("\\."); - return parts.length != 4; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/RouteUtils.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/RouteUtils.java deleted file mode 100644 index 8418fb27..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/RouteUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import com.baidu.cloud.starlight.api.model.Request; -import org.springframework.util.StringUtils; - -/** - * Created by liuruisen on 2021/11/8. - */ -public class RouteUtils { - - private static final String INSTANCE_SPLIT_1 = "\\."; - - private static final String INSTANCE_SPLIT_2 = "-"; - - private static final String CONVERTED_INSTANCE_FORMAT = "%s-%s-%s"; - - public static String convertedInstanceId(String instanceId) { - if (StringUtils.isEmpty(instanceId)) { - return instanceId; - } - String[] metaInfos = instanceId.split(INSTANCE_SPLIT_1); - String[] platformInfos = metaInfos[1].split(INSTANCE_SPLIT_2); - // instanceIdIndex-platform-logicIdc - return String.format(CONVERTED_INSTANCE_FORMAT, metaInfos[0], platformInfos[1], platformInfos[4]); - } - - public static String reqMsg(Request request) { - return request.getId() + "#" + request.getServiceName() + "#" + request.getMethodName(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/SpringCloudConstants.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/SpringCloudConstants.java deleted file mode 100644 index a3b80a3e..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/common/SpringCloudConstants.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -/** - * Created by liuruisen on 2020/3/2. - */ -public class SpringCloudConstants { - - /** - * Local host name, used in server side - */ - public static final String LOCAL_HOST_NAME = "localhost"; - - /** - * StarlightServer bean name - */ - public static final String STARLIGHT_SERVER_NAME = "StarlightServer"; - - /** - * Used to assemble service bean name - */ - public static final String BEAN_NAME_SEPARATOR = ":"; - - /** - * Default Cluster model - */ - public static final String DEFAULT_CLUSTER_MODEL = "failfast"; - - /** - * Default warm up ration 100 present all instance will be init - */ - public static final Integer DEFAULT_WARM_UP_RATIO = 100; - - /** - * Client default filters, outlierdetect - context - monitor - */ - public static final String DEFAULT_CLIENT_FILTERS = "outlierdetect,clientcontext,clientmonitor"; - // + ",formulacircuitbreaker,formularequestdecorate"; - - /** - * Server default filters, context - generic - monitor - */ - public static final String DEFAULT_SERVER_FILTERS = "servercontext,generic,servermonitor"; - // + ",formularatelimiter"; - - /** - * Cloud Env - */ - public static final String PAAS_TYPE = "EM_PAAS_TYPE"; - - /** - * CCE container - */ - public static final String PAAS_TYPE_CCE = "CCE"; - - /** - * BCC container - */ - public static final String PAAS_TYPE_BCC = "BCC"; - - /** - * Jarvis platform environment variables: EM_APP - */ - public static final String EM_APP = "EM_APP"; - - /** - * Jarvis platform environment variables: EM_PRODUCT_LINE - */ - public static final String EM_PRODUCT_LINE = "EM_PRODUCT_LINE"; - - /** - * Jarvis platform environment variables: EM_PLATFORM - */ - public static final String EM_PLATFORM = "EM_PLATFORM"; - - /** - * starlight.server.name key name - */ - public static final String STARLIGHT_SERVER_NAME_KEY = "starlight.server.name"; - - /** - * spring application name key name - */ - public static final String SPRING_APPLICATION_NAME_KEY = "spring.application.name"; - - /** - * starlight server port key name - */ - public static final String STARLIGHT_SERVER_PORT_KEY = "starlight.server.port"; - - /** - * Server port key - */ - public static final String SERVER_PORT_KEY = "server.port"; - - /** - * default retry times, used in failover cluster client - */ - public static final Integer DEFAULT_RETRY_TIMES = 2; - - /** - * default retry delay mills, used in failover cluster client - */ - public static final Integer DEFAULT_RETRY_DELAY_MILLS = 100; - - public static final String RETRYABLE_SPLIT_KEY = ","; - - /** - * Used to identify the server instance launch and register time - */ - public static final String EPOCH_KEY = "EPOCH"; - - public static final String PROTOCOLS_KEY = "protocols"; - - public static final String INTERFACES_KEY = "interfaces"; - - public static final String OUTLIER_STATS_KEY = "outlier_stats"; - - public static final String OUTLIER_DETECT_ENABLED_KEY = "outlier_detect_enabled"; - - public static final Boolean OUTLIER_DETECT_ENABLED = false; - - /** - * Outlier detect: detect interval key - */ - public static final String OUTLIER_DETECT_INTERVAL_KEY = "outlier_detect_interval"; - - /** - * Outlier detect: default value of outlier detect interval 30s - */ - public static final Integer OUTLIER_DETECT_INTERVAL = 30; - - /** - * Outlier detect: Minimum number of requests key - */ - public static final String OUTLIER_DETECT_MINI_REQUEST_NUM_KEY = "outlier_detect_mini_request_num"; - - /** - * Outlier detect: Default value of minimum number of requests 5 - */ - public static final Integer OUTLIER_DETECT_MINI_REQUEST_NUM = 5; - - /** - * Outlier detect: Request fail percent threshold key - */ - public static final String OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY = "outlier_detect_fail_percent_threshold"; - - /** - * Outlier detect: Default value of request fail percent threshold 20% - */ - public static final Integer OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD = 20; - - /** - * Outlier detect: Request fail count threshold key - */ - public static final String OUTLIER_DETECT_FAIL_COUNT_THRESHOLD_KEY = "outlier_detect_fail_count_threshold"; - - /** - * Outlier detect: Default value of request fail count threshold 5 - */ - public static final Integer OUTLIER_DETECT_FAIL_COUNT_THRESHOLD = 5; - - /** - * Outlier detect: Base eject time key - */ - public static final String OUTLIER_DETECT_BASE_EJECT_TIME_KEY = "outlier_detect_base_eject_time"; - - /** - * Outlier detect: Default value of base eject time 30s - */ - public static final Integer OUTLIER_DETECT_BASE_EJECT_TIME = 30; - - /** - * Outlier detect: Max eject time key - */ - public static final String OUTLIER_DETECT_MAX_EJECT_TIME_KEY = "outlier_detect_max_eject_time"; - - /** - * Outlier detect: Default value of max eject time 600s - */ - public static final Integer OUTLIER_DETECT_MAX_EJECT_TIME = 600; - - /** - * Outlier detect: Max eject percent key - */ - public static final String OUTLIER_DETECT_MAX_EJECT_PERCENT_KEY = "outlier_detect_max_eject_percent"; - - /** - * Outlier detect: Default value of max eject percent 20% - */ - public static final Integer OUTLIER_DETECT_MAX_EJECT_PERCENT = 20; - - /** - * The execution order of shutting down server list filter, third - */ - public static final Integer SHUTTING_DOWN_SERVER_LIST_FILTER_ORDER = 3; - - /** - * The execution order of outlier server list filter, second - */ - public static final Integer OUTLIER_SEVER_LIST_FILTER_ORDER = 2; - - /** - * The execution order of route server list filter, first - */ - public static final Integer ROUTE_SERVER_LIST_FILTER_ORDER = 1; - - /** - * How many times will retry when network error occur - */ - public static final Integer NETWORK_ERROR_RETRY_TIMES = 3; - - /** - * Spring cloud heart beat time out - */ - public static final Integer HEARTBEAT_REQUEST_TIMEOUT = 1000; - - /** - * Default value of local cache enabled: true - */ - public static final Boolean LOCAL_CACHE_ENABLED = true; - - /** - * Default value of whether to store asynchronously - */ - public static final Boolean STORE_LOCAL_CACHE_ASYNC = false; - - /* - * The execution order of outlier server list filter, second - */ - public static final Boolean OUTLIER_RECOVER_BY_CHECK_ENABLED = true; - - /** - * 用于执行路由 - */ - public static final String REQUEST_ROUTE_KEY = "req_route_meta"; - - /** - * No instance available error code - */ - public static final Integer NO_INSTANCE_ERROR_CODE = 1008; - - public static final String RDS_KEY = "RDS"; - - public static final String LABEL_SELECTOR_ROUTE_KEY = "label_selector_route"; - - /** - * 请求级别的label selector,当前用于海若场景 - */ - public static final String REQUEST_LABEL_SELECTOR_ROUTE_KEY = "request_label_selector_route"; - - public static final String ROUTE_CONTEXT_KEY = "route_context"; -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ChangeType.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ChangeType.java deleted file mode 100644 index 4728b745..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ChangeType.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.configuration; - -/** - * Created by liuruisen on 2021/9/6. - */ -public enum ChangeType { - - ADD("add"), UPDATE("update"), DELETE("delete"); - - private String name; - - ChangeType(String name) { - this.name = name; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigChangeEvent.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigChangeEvent.java deleted file mode 100644 index 2deabc10..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigChangeEvent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.configuration; - -/** - * Created by liuruisen on 2021/9/6. - */ -public class ConfigChangeEvent { - - private Object configContent; - - private ChangeType changeType; - - public ConfigChangeEvent(Object configContent) { - this.configContent = configContent; - } - - public ConfigChangeEvent(Object configContent, ChangeType changeType) { - this.configContent = configContent; - this.changeType = changeType; - } - - public Object getConfigContent() { - return configContent; - } - - public void setConfigContent(Object configContent) { - this.configContent = configContent; - } - - public ChangeType getChangeType() { - return changeType; - } - - public void setChangeType(ChangeType changeType) { - this.changeType = changeType; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ConfigChangeEvent{"); - sb.append("configContent=").append(configContent); - sb.append(", changeType=").append(changeType); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigListener.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigListener.java deleted file mode 100644 index 90155dd3..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/ConfigListener.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.configuration; - -/** - * Created by liuruisen on 2021/9/6. - */ -public interface ConfigListener { - - /** - * should try-catch exception - * - * @param event - */ - void onConfigChange(ConfigChangeEvent event); - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/Configuration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/Configuration.java deleted file mode 100644 index 8ce3d033..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/configuration/Configuration.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.configuration; - -/** - * Subscribe and get configuration info from config center Created by liuruisen on 2021/9/6. - */ -public interface Configuration { - - /** - * subscribe - * - * @param key - * @param group - * @param listener - */ - void subscribeConfig(String key, String group, ConfigListener listener); - - /** - * unsubscribe - * - * @param key - * @param group - */ - void unsubscribeConfig(String key, String group); - - /** - * Get config from cache - * - * @param key - * @param group - * @return - */ - Object getConfig(String key, String group); -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycle.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycle.java deleted file mode 100644 index a403b000..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycle.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.lifecycle; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.SmartLifecycle; - -import com.baidu.cloud.starlight.springcloud.client.cluster.FailFastClusterClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.FailOverClusterClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; - -public class StarlightClientLifecycle implements SmartLifecycle { - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightClientLifecycle.class); - - private volatile boolean running = false; - - private volatile boolean firstStart = true; - - private final SingleStarlightClientManager singleStarlightClientManager; - - private final ApplicationContext applicationContext; - - public StarlightClientLifecycle(SingleStarlightClientManager singleStarlightClientManager, - ApplicationContext applicationContext) { - this.singleStarlightClientManager = singleStarlightClientManager; - this.applicationContext = applicationContext; - } - - @Override - public void start() { - LOGGER.info("StarlightClientLifecycle start: thread: {}, loader:{}", Thread.currentThread(), - Thread.currentThread().getContextClassLoader()); - // 初始化 Client, ClusterClient 或者 SingleClient - if (!firstStart) { - for (String beanName : applicationContext.getBeanNamesForType(FailFastClusterClient.class)) { - FailFastClusterClient client = (FailFastClusterClient) applicationContext.getBean(beanName); - client.init(); - } - for (String beanName : applicationContext.getBeanNamesForType(FailOverClusterClient.class)) { - FailOverClusterClient client = (FailOverClusterClient) applicationContext.getBean(beanName); - client.init(); - } - } - - this.running = true; - this.firstStart = false; - } - - @Override - public void stop(Runnable callback) { - LOGGER.info("StarlightClientLifecycle stop: thread: {}, loader:{}", Thread.currentThread(), - Thread.currentThread().getContextClassLoader()); - - singleStarlightClientManager.destroyAll(); - - this.running = false; - callback.run(); - } - - @Override - public void stop() { - throw new UnsupportedOperationException("Stop must not be invoked directly"); - } - - @Override - public boolean isRunning() { - return this.running; - } - - @Override - public boolean isAutoStartup() { - return true; - } - - /** - * phase 越小,越早执行 start(), 越晚执行 stop() 设计 Client 的 phase 大于 server - * - * @return - */ - @Override - public int getPhase() { - return Integer.MAX_VALUE - 11; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycleAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycleAutoConfiguration.java deleted file mode 100644 index 7798d730..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightClientLifecycleAutoConfiguration.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.lifecycle; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.baidu.cloud.starlight.springcloud.client.StarlightClientAutoConfiguration; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; - -@Configuration -@AutoConfigureAfter(value = {StarlightClientAutoConfiguration.class}) -@ConditionalOnBean(value = {SingleStarlightClientManager.class}) -public class StarlightClientLifecycleAutoConfiguration { - @Bean - public StarlightClientLifecycle starlightClientLifecycle(SingleStarlightClientManager singleStarlightClientManager, - ApplicationContext applicationContext) { - return new StarlightClientLifecycle(singleStarlightClientManager, applicationContext); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycle.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycle.java deleted file mode 100644 index 8d6f1062..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycle.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.lifecycle; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.SmartLifecycle; - -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.core.rpc.DefaultStarlightServer; -import com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterListener; - -/** - * Created by liuruisen on 2020/12/3. - */ - -public class StarlightServerLifecycle implements SmartLifecycle { - - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightServerLifecycle.class); - - private volatile boolean running = false; - - private volatile boolean firstStart = true; - - private final StarlightServer starlightServer; - - private final StarlightRegisterListener registerListener; - - private final ApplicationContext applicationContext; - - public StarlightServerLifecycle(StarlightServer starlightServer, StarlightRegisterListener registerListener, - ApplicationContext applicationContext) { - this.starlightServer = starlightServer; - this.registerListener = registerListener; - this.applicationContext = applicationContext; - } - - @Override - public boolean isAutoStartup() { - return true; - } - - @Override - public void start() { - LOGGER.info("StarlightServerLifecycle start: thread: {}, loader:{}", Thread.currentThread(), - Thread.currentThread().getContextClassLoader()); - - // Server Restore - if (!firstStart) { - if (starlightServer instanceof DefaultStarlightServer defaultStarlightServer) { - // 如果未使用 Gravity, 例如使用 Consul 注册,则体现为 Restore 时不设置新端口,不支持 CRaC - defaultStarlightServer.restart(); - defaultStarlightServer.serve(); - } else { - LOGGER.error("DefaultStarlightServer required!"); - } - } - - if (firstStart) { - registerListener.register(applicationContext); - } else { - registerListener.restartRegisterExecutor(); - // 同上,未使用 Gravity, 则 Restore 阶段不会重新注册,不支持 CRaC - } - - this.running = true; - this.firstStart = false; - } - - /** - * stop(Runnable callback); callback 由 Spring 框架传入, 用于通知 Spring 容器该组件已经安全停止 - * - * @param callback - */ - @Override - public void stop(Runnable callback) { - LOGGER.info("StarlightServerLifecycle stop: thread: {}, loader:{}", Thread.currentThread(), - Thread.currentThread().getContextClassLoader()); - - registerListener.deRegister(); // async and catch error - - starlightServer.destroy(); // catch error - - // deRegister() 是一个异步动作,sleep 若干秒等待其完成 - try { - LOGGER.info("StarlightServerLifecycle.stop(), wait 10s until operation complete"); - Thread.sleep(10 * 1000); - } catch (InterruptedException e) { - LOGGER.info("StarlightServerLifecycle.stop(), InterruptedException", e); - } - - this.running = false; - - // unlock and perform next shutdown process - callback.run(); - } - - @Override - public void stop() { - throw new UnsupportedOperationException("Stop must not be invoked directly"); - } - - @Override - public boolean isRunning() { - return this.running; - } - - @Override - public int getPhase() { - return Integer.MAX_VALUE - 10; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycleAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycleAutoConfiguration.java deleted file mode 100644 index aadbfe07..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/lifecycle/StarlightServerLifecycleAutoConfiguration.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.lifecycle; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.springcloud.server.StarlightServerAutoConfiguration; -import com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterAutoConfiguration; -import com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterListener; - -/** - * Created by liuruisen on 2020/12/3. - */ -@Configuration -@AutoConfigureAfter(value = {StarlightServerAutoConfiguration.class, StarlightRegisterAutoConfiguration.class}) -@ConditionalOnBean(value = {StarlightServer.class, StarlightRegisterListener.class}) -public class StarlightServerLifecycleAutoConfiguration { - @Bean - @ConditionalOnMissingBean - public StarlightServerLifecycle starlightServerLifecycle(StarlightServer starlightServer, - StarlightRegisterListener starlightRegisterListener, ApplicationContext applicationContext) { - return new StarlightServerLifecycle(starlightServer, starlightRegisterListener, applicationContext); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfiguration.java deleted file mode 100644 index dfb9435c..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server; - -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.core.rpc.DefaultStarlightServer; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.common.ConstantUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.concurrent.ThreadFactory; - -/** - * Created by liuruisen on 2020/3/5. - */ -@Configuration -@ConditionalOnClass(RpcService.class) -@EnableConfigurationProperties(StarlightServerProperties.class) -@ConditionalOnProperty(value = "starlight.server.enable") -public class StarlightServerAutoConfiguration { - - @Bean(name = SpringCloudConstants.STARLIGHT_SERVER_NAME) - public StarlightServer starlightServer(StarlightServerProperties serverProperties, - @Qualifier(value = ConstantUtils.STARLIGHT_NETTY_SERVER_FACTORY) ObjectProvider< - ThreadFactory> threadFactoryProvider) { - StarlightServer starlightServer = - new DefaultStarlightServer(null, serverProperties.getHost(), ApplicationContextUtils.getServerPort(), - serverProperties.transportConfig(), threadFactoryProvider.getIfAvailable()); - starlightServer.init(); - starlightServer.serve(); - return starlightServer; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/RpcService.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/RpcService.java deleted file mode 100644 index 3bb96146..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/RpcService.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.annotation; - -import org.springframework.stereotype.Component; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * RpcService annotation Created by liuruisen on 2020/3/2. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Component -public @interface RpcService { - - /** - * Specify the serviceId when the service name is not equal to the interface name - * - * @return - */ - String serviceId() default ""; - - /** - * What protocol is used to access the service - * - * @return - */ - String protocol() default ""; - - /** - * Service Level Filter - * - * @return - */ - String filters() default ""; - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/StarlightScan.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/StarlightScan.java deleted file mode 100644 index a437889e..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/annotation/StarlightScan.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.annotation; - -import com.baidu.cloud.starlight.springcloud.server.service.RpcServicesRegistrar; -import org.springframework.context.annotation.Import; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created by liuruisen on 2020/3/5. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import({RpcServicesRegistrar.class}) -public @interface StarlightScan { - - /** - * BasePackages to scan for {@link RpcService} classes. TODO future feature - * - * @return - */ - String[] basePackages() default {}; -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerProperties.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerProperties.java deleted file mode 100644 index 8cc6209c..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerProperties.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.properties; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Global configuration for all RpcProxies Created by liuruisen on 2019-07-10. - */ -@ConfigurationProperties(prefix = StarlightServerProperties.PREFIX) -public class StarlightServerProperties { - static final String PREFIX = "starlight.server"; - - private String name; - - private Integer port; - - private String host; - - private boolean enable; - - private String protocols = Constants.SERVER_PROTOCOLS; // server support protocols - - private String compressType = "none"; - - private String filters; // split by "," global level - - private Integer allIdleTimeout = Constants.ALL_IDLE_TIMEOUT_VALUE; // second - - private Integer ioThreadNum = Constants.DEFAULT_IO_THREADS_VALUE; - - private Integer acceptThreadNum = Constants.DEFAULT_ACCEPTOR_THREAD_VALUE; - - private Integer writeTimeoutMills = Constants.WRITE_TIMEOUT_VALUE; - - private GracefullyShutdown shutdown = new GracefullyShutdown(); - - private Boolean connectKeepAliveEnable; - - private Integer registerDelay; // register after n s after SpringApplication started - - private Integer bizThreadNum; // env var > default 500 - - private Integer ioRatio; // netty ioRatio, default 100 - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getProtocols() { - return protocols; - } - - public void setProtocols(String protocols) { - this.protocols = protocols; - } - - public String getCompressType() { - return compressType; - } - - public void setCompressType(String compressType) { - this.compressType = compressType; - } - - public String getFilters() { - return filters; - } - - public void setFilters(String filters) { - this.filters = filters; - } - - public Integer getAllIdleTimeout() { - return allIdleTimeout; - } - - public void setAllIdleTimeout(Integer allIdleTimeout) { - this.allIdleTimeout = allIdleTimeout; - } - - public Integer getIoThreadNum() { - return ioThreadNum; - } - - public void setIoThreadNum(Integer ioThreadNum) { - this.ioThreadNum = ioThreadNum; - } - - public Integer getAcceptThreadNum() { - return acceptThreadNum; - } - - public void setAcceptThreadNum(Integer acceptThreadNum) { - this.acceptThreadNum = acceptThreadNum; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public Integer getWriteTimeoutMills() { - return writeTimeoutMills; - } - - public void setWriteTimeoutMills(Integer writeTimeoutMills) { - this.writeTimeoutMills = writeTimeoutMills; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public boolean getEnable() { - return enable; - } - - public void setEnable(boolean enable) { - this.enable = enable; - } - - public GracefullyShutdown getShutdown() { - return shutdown; - } - - public void setShutdown(GracefullyShutdown shutdown) { - this.shutdown = shutdown; - } - - public Boolean getConnectKeepAliveEnable() { - return connectKeepAliveEnable; - } - - public void setConnectKeepAliveEnable(Boolean connectKeepAliveEnable) { - this.connectKeepAliveEnable = connectKeepAliveEnable; - } - - public Integer getRegisterDelay() { - return registerDelay; - } - - public void setRegisterDelay(Integer registerDelay) { - this.registerDelay = registerDelay; - } - - public Integer getBizThreadNum() { - return bizThreadNum; - } - - public void setBizThreadNum(Integer bizThreadNum) { - this.bizThreadNum = bizThreadNum; - } - - public Integer getIoRatio() { - return ioRatio; - } - - public void setIoRatio(Integer ioRatio) { - this.ioRatio = ioRatio; - } - - public TransportConfig transportConfig() { - TransportConfig transportConfig = new TransportConfig(); - transportConfig.setAcceptThreadNum(this.acceptThreadNum); - transportConfig.setIoThreadNum(this.ioThreadNum); - transportConfig.setAllIdleTimeout(this.allIdleTimeout); - transportConfig.setWriteTimeoutMills(this.writeTimeoutMills); - transportConfig.setGracefullyShutdown(shutdown.getGracefully()); - transportConfig.setGracefullyQuietPeriod(shutdown.getQuietPeriod()); - transportConfig.setGracefullyTimeout(shutdown.getTimeout()); - transportConfig.setConnectKeepAliveEnable(this.connectKeepAliveEnable); - transportConfig.setBizWorkThreadNum(this.bizThreadNum); - transportConfig.setIoRatio(this.ioRatio); - return transportConfig; - } - - public class GracefullyShutdown { - - private boolean gracefully = true; - - private Integer quietPeriod = 2; // 2s - - private Integer timeout = 30; // 30s - - public boolean getGracefully() { - return gracefully; - } - - public void setGracefully(boolean gracefully) { - this.gracefully = gracefully; - } - - public Integer getQuietPeriod() { - return quietPeriod; - } - - public void setQuietPeriod(Integer quietPeriod) { - this.quietPeriod = quietPeriod; - } - - public Integer getTimeout() { - return timeout; - } - - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterAutoConfiguration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterAutoConfiguration.java deleted file mode 100644 index d9391b4a..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterAutoConfiguration.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register; - -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.springcloud.server.register.consul.StarlightConsulRegisterListener; -import com.baidu.cloud.starlight.springcloud.server.register.gravity.StarlightGravityRegisterListener; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Created by liuruisen on 2020/12/3. - */ -@Configuration -@AutoConfigureAfter(name = {"com.baidu.cloud.starlight.springcloud.server.StarlightServerAutoConfiguration", - "org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration", - "com.baidu.formula.discovery.serviceregistry.FormulaServiceRegistryAutoConfiguration", - "com.baidu.cloud.gravity.discovery.registry.GravityAutoServiceRegistrationAutoConfiguration"}) -@ConditionalOnClass(name = "org.springframework.cloud.client.discovery.DiscoveryClient") -@ConditionalOnProperty(name = "spring.cloud.discovery.enabled", matchIfMissing = true) -@ConditionalOnBean(StarlightServer.class) -public class StarlightRegisterAutoConfiguration { - - @Configuration - @ConditionalOnClass( - name = "com.baidu.cloud.gravity.discovery.registry.GravityAutoServiceRegistrationAutoConfiguration") - protected static class StarlightGravityRegisterAutoConfiguration { - - @Bean(destroyMethod = "destroy") - @ConditionalOnMissingBean - @ConditionalOnBean( - type = "com.baidu.cloud.gravity.discovery.registry.GravityAutoServiceRegistrationAutoConfiguration") - public StarlightGravityRegisterListener starlightGravityRegisterListener() { - return new StarlightGravityRegisterListener(); - } - } - - @Configuration - @ConditionalOnClass(ConsulServiceRegistryAutoConfiguration.class) - protected static class StarlightConsulRegisterAutoConfiguration { - - @Bean(destroyMethod = "destroy") - @ConditionalOnMissingBean - @ConditionalOnBean(ConsulServiceRegistryAutoConfiguration.class) - public StarlightRegisterListener consulRegisterListener() { - return new StarlightConsulRegisterListener(); - } - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListener.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListener.java deleted file mode 100644 index b30a3eaf..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListener.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.client.serviceregistry.Registration; -import org.springframework.cloud.client.serviceregistry.ServiceRegistry; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.Environment; - -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.starlight.api.utils.NetUriUtils; -import com.baidu.cloud.starlight.core.rpc.RpcServiceRegistry; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import com.baidu.cloud.thirdparty.jackson.core.JsonProcessingException; - -/** - * Listen to ApplicationStartedEvent and perform service registration Created by liuruisen on 2020/3/2. - */ -public abstract class StarlightRegisterListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightRegisterListener.class); - - protected ServiceRegistry serviceRegistry; - - protected ApplicationContext applicationContext; - - protected Registration registration; - - protected StarlightServerProperties serverProperties; - - protected static final String RPC_TYPE = "rpc"; - - private ExecutorService registerExecutor = - Executors.newSingleThreadExecutor(new NamedThreadFactory("StarlightRegisterWorker")); - - /** - * Register and deregister thread pool, single - */ - public void restartRegisterExecutor() { - this.registerExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory("StarlightRegisterWorker")); - } - - public void register(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class); - this.serverProperties = applicationContext.getBean(StarlightServerProperties.class); - Integer registerDelay = serverProperties.getRegisterDelay(); - if (registerDelay != null && registerDelay > 0) { - try { - TimeUnit.SECONDS.sleep(registerDelay); - } catch (InterruptedException e) { - LOGGER.warn("Exception occur when delay before register, cause by {}", e.getMessage()); - } - } - // create StarlightRegistration - registration = createStarlightRegistration(); - // register StarlightRegistration - registerExecutor.execute(() -> { - try { - LOGGER.info("Register starlight server instance {}:{} start", registration.getHost(), - registration.getPort()); - serviceRegistry.register(registration); - LOGGER.info("Register starlight server instance {}:{} success", registration.getHost(), - registration.getPort()); - } catch (Throwable e) { - LOGGER.warn("Register server instance {}:{} failed, cause by ", registration.getHost(), - registration.getPort(), e); - } - }); - } - - /** - * CRaC Restore 之后, 基于新实例的相关信息, 进行 RPC 注册 和 register() 的主要区别: 更新了 registration.port - * - * @param port - */ - public void reRegister(ApplicationContext applicationContext, Integer port) { - this.applicationContext = applicationContext; - this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class); - this.serverProperties = applicationContext.getBean(StarlightServerProperties.class); - Integer registerDelay = serverProperties.getRegisterDelay(); - if (registerDelay != null && registerDelay > 0) { - try { - TimeUnit.SECONDS.sleep(registerDelay); - } catch (InterruptedException e) { - LOGGER.warn("Exception occur when delay before register, cause by {}", e.getMessage()); - } - } - - registration = updateStarlightRegistration(registration, port); - - // register StarlightRegistration - registerExecutor.execute(() -> { - try { - LOGGER.info("Register starlight server instance {}:{} start", - registration.getHost() == null ? NetUriUtils.getLocalHost() : registration.getHost(), - registration.getPort()); - serviceRegistry.register(registration); - LOGGER.info("Register starlight server instance {}:{} success", - registration.getHost() == null ? NetUriUtils.getLocalHost() : registration.getHost(), - registration.getPort()); - } catch (Throwable e) { - LOGGER.warn("Register server instance {}:{} failed, cause by ", registration.getHost(), - registration.getPort(), e); - } - }); - } - - protected abstract Registration createStarlightRegistration(); - - protected Registration updateStarlightRegistration(Registration oldRegistration, Integer port) { - return null; - } - - /** - * Get starlight app name AppName will serve as the service discovery name for SpringCloud - * - * @param env - * @return - */ - protected String getAppName(Environment env) { - return ApplicationContextUtils.getApplicationName(); - } - - /** - * Get port - * - * @param env - * @return - */ - protected Integer getPort(Environment env) { - return ApplicationContextUtils.getServerPort(); - } - - /** - * Generate Starlight InstanceId: appName-ip-port-rpc - * - * @param env - * @return - */ - protected String getInstanceId(Environment env) { - String appName = getAppName(env); - Integer port = getPort(env); - String instanceId = "instanceId"; - return String.format("%s-%s-%s-rpc", appName, port, instanceId); - } - - /** - * Get service interface name that exported to Starlight Server - * - * @return - */ - protected List getInterfaces() { - List interfaces = new LinkedList<>(); - Set serviceInvokers = RpcServiceRegistry.getInstance().rpcServices(); - if (serviceInvokers != null) { - for (ServiceInvoker invoker : serviceInvokers) { - if (invoker.getRpcService().getServiceClass() != HeartbeatService.class) { - interfaces.add(invoker.getRpcService().getServiceClass().getName()); - } - } - } - return interfaces; - } - - // @PreDestroy - // The timing of the de-registration call is changed to Gracefully - public void deRegister() { - if (registration != null) { - registerExecutor.execute(() -> { - try { - LOGGER.info("Deregister server instance {}:{} start", registration.getHost(), - registration.getPort()); - serviceRegistry.deregister(registration); - LOGGER.info("Deregister server instance {}:{} success", registration.getHost(), - registration.getPort()); - } catch (Exception e) { - LOGGER.warn("Deregister server instance failed, cause by: ", e); - } - }); - } - } - - protected Map starlightMetas() { - Map starlightMetas = new HashMap<>(); - String protocols = applicationContext.getBean(StarlightServerProperties.class).getProtocols(); - starlightMetas.put(SpringCloudConstants.PROTOCOLS_KEY, protocols); // protocols meta - try { - List interfaces = getInterfaces(); // interfaces meta - starlightMetas.put(SpringCloudConstants.INTERFACES_KEY, - JsonSerializer.OBJECT_MAPPER.writeValueAsString(interfaces)); - } catch (JsonProcessingException e) { - throw new IllegalStateException("Add interfaces to register meta failed.", e); - } - // epoch represents the start time of the current server - starlightMetas.put(SpringCloudConstants.EPOCH_KEY, String.valueOf(System.currentTimeMillis())); - return starlightMetas; - } - - public void destroy() { - LOGGER.info("Shutdown the Executor pool for StarlightRegisterListener"); - registerExecutor.shutdown(); - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListener.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListener.java deleted file mode 100644 index 2e351ea6..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListener.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.consul; - -import com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterListener; -import com.ecwid.consul.v1.agent.model.NewService; -import org.springframework.cloud.client.serviceregistry.Registration; -import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties; -import org.springframework.cloud.consul.discovery.HeartbeatProperties; -import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -import java.util.HashMap; -import java.util.Map; - -/** - * Register Starlight Service to Consul Created by liuruisen on 2020/3/2. - */ -public class StarlightConsulRegisterListener extends StarlightRegisterListener { - - @Override - protected Registration createStarlightRegistration() { - ConsulDiscoveryProperties discoveryProperties = applicationContext.getBean(ConsulDiscoveryProperties.class); - HeartbeatProperties heartbeatProperties = applicationContext.getBean(HeartbeatProperties.class); - // Create NewService - String appName = getAppName(applicationContext.getEnvironment()); // appName - NewService service = new NewService(); - service.setName(appName); // name - - service.setId(getInstanceId(applicationContext.getEnvironment())); // instanceId - if (discoveryProperties.getInstanceId() != null) { - service.setId(discoveryProperties.getInstanceId()); - } - - if (!discoveryProperties.isPreferAgentAddress()) { - service.setAddress(discoveryProperties.getHostname()); // address - } - - service.setPort(getPort(applicationContext.getEnvironment())); // port - - service.setMeta(getMetadata(discoveryProperties)); - service.setCheck(createCheck(service.getPort(), heartbeatProperties, discoveryProperties)); // rpc check - - return new ConsulRegistration(service, discoveryProperties); - } - - /*** - * Rpc service Check - * - * @return - */ - public static NewService.Check createCheck(Integer port, HeartbeatProperties ttlConfig, - ConsulDiscoveryProperties properties) { - NewService.Check check = new NewService.Check(); - if (ttlConfig.isEnabled()) { - check.setTtl(ttlConfig.getTtl().getSeconds() + "s"); - // Note. Default timeout to deregister services critical for longer than timeout (e.g. 3m). - check.setDeregisterCriticalServiceAfter("3m"); - if (StringUtils.hasText(properties.getHealthCheckCriticalTimeout())) { - check.setDeregisterCriticalServiceAfter(properties.getHealthCheckCriticalTimeout()); - } - return check; - } - - Assert.notNull(port, "createCheck port must not be null"); - Assert.isTrue(port > 0, "createCheck port must be greater than 0"); - - // TCP Check - check.setTcp(String.format("%s:%s", properties.getHostname(), port)); - - check.setInterval(properties.getHealthCheckInterval()); - check.setTimeout(properties.getHealthCheckTimeout()); - if (StringUtils.hasText(properties.getHealthCheckCriticalTimeout())) { - check.setDeregisterCriticalServiceAfter(properties.getHealthCheckCriticalTimeout()); - } - check.setTlsSkipVerify(properties.getHealthCheckTlsSkipVerify()); - return check; - } - - private Map getMetadata(ConsulDiscoveryProperties properties) { - Map metadata = new HashMap<>(); - if (!CollectionUtils.isEmpty(properties.getMetadata())) { - metadata.putAll(properties.getMetadata()); - } - - // add metadata from other properties. See createTags above. - if (!StringUtils.hasLength(properties.getInstanceZone())) { - metadata.put(properties.getDefaultZoneMetadataName(), properties.getInstanceZone()); - } - if (!StringUtils.hasLength(properties.getInstanceGroup())) { - metadata.put("group", properties.getInstanceGroup()); - } - - // store the secure flag in the tags so that clients will be able to figure - // out whether to use http or https automatically - metadata.put("secure", Boolean.toString(properties.getScheme().equalsIgnoreCase("https"))); - - // add starlight metadata - metadata.putAll(starlightMetas()); - - return metadata; - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistration.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistration.java deleted file mode 100644 index 9011b6ca..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistration.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.gravity; - -import org.springframework.cloud.client.serviceregistry.Registration; - -import java.net.URI; -import java.util.Map; - -/** - * gravity-spring-cloud-starter support convert Registration to Gravity Endpoint so we implements registration as - * GravityRegistration Created by liuruisen on 2020/8/13. - */ -public class GravityRegistration implements Registration { - - private String serviceId; - - private String host; - - private Integer port; - - private String schema; - - private Map metadata; - - @Override - public String getServiceId() { - return serviceId; - } - - @Override - public String getHost() { - return host; - } - - @Override - public int getPort() { - return port; - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public URI getUri() { - String uri = String.format("%s://%s:%s", schema, host, port); - return URI.create(uri); - } - - @Override - public Map getMetadata() { - return metadata; - } - - @Override - public String getScheme() { - return schema; - } - - public void setServiceId(String serviceId) { - this.serviceId = serviceId; - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(Integer port) { - this.port = port; - } - - public void setSchema(String schema) { - this.schema = schema; - } - - public void setMetadata(Map metadata) { - this.metadata = metadata; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListener.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListener.java deleted file mode 100644 index abaa1990..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListener.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.gravity; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.cloud.client.serviceregistry.Registration; - -import com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterListener; - -/** - * Created by liuruisen on 2020/8/10. - */ -public class StarlightGravityRegisterListener extends StarlightRegisterListener { - - @Override - protected Registration createStarlightRegistration() { - GravityRegistration registration = new GravityRegistration(); - registration.setServiceId(getAppName(applicationContext.getEnvironment())); - registration.setPort(getPort(applicationContext.getEnvironment())); - registration.setSchema(RPC_TYPE); - - // metadata - Map metadata = registration.getMetadata(); - if (metadata == null) { - metadata = new LinkedHashMap<>(); - } - metadata.putAll(starlightMetas()); - registration.setMetadata(metadata); - - return registration; - } - - @Override - protected Registration updateStarlightRegistration(Registration oldRegistration, Integer port) { - GravityRegistration newRegistration = new GravityRegistration(); - newRegistration.setPort(port); - newRegistration.setServiceId(oldRegistration.getServiceId()); - newRegistration.setSchema(RPC_TYPE); - - // 不复用 oldRegistration 的 metadata, - // 因为其中的 EPOCH 时间戳需要更新,Consumer 端根据时间戳判断 Provider 是否重启了 - Map metadata = newRegistration.getMetadata(); - if (metadata == null) { - metadata = new LinkedHashMap<>(); - } - metadata.putAll(starlightMetas()); - newRegistration.setMetadata(metadata); - - return newRegistration; - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServiceBean.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServiceBean.java deleted file mode 100644 index 5c24c840..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServiceBean.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.StringUtils; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; - -/** - * Created by liuruisen on 2019-05-23. - */ - -public class RpcServiceBean implements InitializingBean { - private StarlightServer starlightServer; - - private Object target; - - private Class targetInterfaceClass; - - @Autowired - private StarlightServerProperties properties; - - private RpcService annotation; - - private com.baidu.cloud.starlight.api.rpc.RpcService rpcService; - - @Override - public void afterPropertiesSet() throws Exception { - ServiceConfig serviceConfig = serviceConfig(annotation, properties); - rpcService = new com.baidu.cloud.starlight.api.rpc.RpcService(targetInterfaceClass, target, serviceConfig); - starlightServer.export(rpcService); - } - - private ServiceConfig serviceConfig(RpcService annotation, StarlightServerProperties properties) { - if (annotation == null && properties == null) { - return null; - } - - ServiceConfig serviceConfig = new ServiceConfig(); - if (properties != null) { - serviceConfig.setFilters(properties.getFilters()); - } - - if (annotation != null) { - if (!StringUtils.isEmpty(annotation.filters())) { - serviceConfig.setFilters(annotation.filters()); - } - if (!StringUtils.isEmpty(annotation.protocol())) { - serviceConfig.setProtocol(annotation.protocol()); - } - if (!StringUtils.isEmpty(annotation.serviceId())) { - serviceConfig.setServiceId(annotation.serviceId()); - } - } - // filters - String filters = serviceConfig.getFilters(); - if (filters != null && !filters.isEmpty()) { - filters = SpringCloudConstants.DEFAULT_SERVER_FILTERS + Constants.FILTER_NAME_SPLIT_KEY + filters.trim(); - } else { - filters = SpringCloudConstants.DEFAULT_SERVER_FILTERS; - } - serviceConfig.setFilters(filters); - - return serviceConfig; - } - - public void setStarlightServer(StarlightServer starlightServer) { - this.starlightServer = starlightServer; - } - - public void setTarget(Object target) { - this.target = target; - } - - public void setProperties(StarlightServerProperties properties) { - this.properties = properties; - } - - public void setTargetInterfaceClass(Class targetInterfaceClass) { - this.targetInterfaceClass = targetInterfaceClass; - } - - public void setAnnotation(RpcService annotation) { - this.annotation = annotation; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicePostProcessor.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicePostProcessor.java deleted file mode 100644 index f13a30bc..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicePostProcessor.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.SingletonBeanRegistry; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.BeanNameGenerator; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.EnvironmentAware; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.context.annotation.AnnotationBeanNameGenerator; -import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.env.Environment; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -import java.util.LinkedHashSet; -import java.util.Set; - -import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR; - -/** - * Used to register RpcServiceBean Created by liuruisen on 2020/3/2. - */ -public class RpcServicePostProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware, - EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware, Ordered { - - private static final Logger LOGGER = LoggerFactory.getLogger(RpcServicePostProcessor.class); - - private static final String RPC_SERVICE_BEAN_NAME_SUFFIX = "RpcService"; - - private ApplicationContext applicationContext; - - private Environment environment; - - private ResourceLoader resourceLoader; - - private ClassLoader classLoader; - - private final Set packagesToScan; - - public RpcServicePostProcessor(Set packagesToScan) { - this.packagesToScan = packagesToScan; - } - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - - Set resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); - - if (!resolvedPackagesToScan.isEmpty()) { - registerRpcServiceBean(resolvedPackagesToScan, registry); - } else { - LOGGER.warn("Register RpcService Bean has been ignored: packagesToScan is empty!"); - } - } - - private void registerRpcServiceBean(Set packagesToScan, BeanDefinitionRegistry registry) { - ClassPathBeanDefinitionScanner scanner = - new ClassPathBeanDefinitionScanner(registry, false, environment, resourceLoader); - scanner.addIncludeFilter(new AnnotationTypeFilter(RpcService.class)); - String[] stringPackages = new String[packagesToScan.size()]; - stringPackages = packagesToScan.toArray(stringPackages); - scanner.scan(stringPackages); - - Set definitionHolders = findRpcServiceBeanHolder(packagesToScan, scanner, registry); - - for (BeanDefinitionHolder definitionHolder : definitionHolders) { - BeanDefinition beanDefinition = definitionHolder.getBeanDefinition(); - Class targetClass = ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), classLoader); - if (targetClass.getInterfaces().length == 0) { - throw new IllegalArgumentException("@RpcService should be written on the implementation class, " - + "but is on {" + targetClass.getName() + "}"); - } - Class targetInterfaceClass = targetClass.getInterfaces()[0]; - RpcService rpcService = AnnotationUtils.findAnnotation(targetClass, RpcService.class); - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RpcServiceBean.class); - builder.addPropertyReference("starlightServer", SpringCloudConstants.STARLIGHT_SERVER_NAME); - builder.addPropertyValue("targetInterfaceClass", targetInterfaceClass); - builder.addPropertyReference("target", definitionHolder.getBeanName()); - builder.addPropertyValue("annotation", rpcService); - // builder.addPropertyValue("properties", applicationContext.getBean(StarlightServerProperties.class)); - - BeanDefinition serviceBeanDefinition = builder.getBeanDefinition(); - String serviceBeanName = generateServiceBeanName(rpcService, targetInterfaceClass); - registry.registerBeanDefinition(serviceBeanName, serviceBeanDefinition); - } - } - - private Set findRpcServiceBeanHolder(Set packagesToScan, - ClassPathBeanDefinitionScanner scanner, BeanDefinitionRegistry registry) { - BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry); - Set beanDefinitions = new LinkedHashSet<>(); - for (String basePackage : packagesToScan) { - Set candidates = scanner.findCandidateComponents(basePackage); - for (BeanDefinition candidate : candidates) { - String beanName = beanNameGenerator.generateBeanName(candidate, registry); - BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); - beanDefinitions.add(definitionHolder); - } - } - return beanDefinitions; - } - - /** - * Get BeanNameGenerator - * - * @param registry - * @return - */ - private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) { - BeanNameGenerator beanNameGenerator = null; - if (registry instanceof SingletonBeanRegistry) { - SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry); - beanNameGenerator = - (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); - } - - if (beanNameGenerator == null) { - LOGGER.info("BeanNameGenerator bean can't be found in BeanFactory with name [" - + CONFIGURATION_BEAN_NAME_GENERATOR + "]"); - LOGGER.info("BeanNameGenerator will be a instance of " + AnnotationBeanNameGenerator.class.getName() - + " , it maybe a potential problem on bean name generation."); - beanNameGenerator = new AnnotationBeanNameGenerator(); - } - return beanNameGenerator; - } - - /** - * Generate ServiceBeanName - * - * @param rpcService - * @param targetInterfaceClass - * @return - */ - private String generateServiceBeanName(RpcService rpcService, Class targetInterfaceClass) { - StringBuilder nameBuilder = new StringBuilder(); - nameBuilder.append(targetInterfaceClass.getName()); - nameBuilder.append(SpringCloudConstants.BEAN_NAME_SEPARATOR); - nameBuilder.append(RPC_SERVICE_BEAN_NAME_SUFFIX); - - return nameBuilder.toString(); - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - // do nothing - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } - - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - private Set resolvePackagesToScan(Set packagesToScan) { - Set resolvedPackagesToScan = new LinkedHashSet(packagesToScan.size()); - for (String packageToScan : packagesToScan) { - if (StringUtils.hasText(packageToScan)) { - String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim()); - resolvedPackagesToScan.add(resolvedPackageToScan); - } - } - return resolvedPackagesToScan; - } - - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicesRegistrar.java b/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicesRegistrar.java deleted file mode 100644 index 2e6d3599..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/java/com/baidu/cloud/starlight/springcloud/server/service/RpcServicesRegistrar.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.EnvironmentAware; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.env.Environment; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.util.ClassUtils; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Created by liuruisen on 2019-05-20. - */ -public class RpcServicesRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { - - private static final String STARLIGHT_SERVER_ENABLE_KEY = "starlight.server.enable"; - - private static final String SERVER_ENABLE = "true"; - private Environment environment; - - // ImportBeanDefinitionRegistrar method - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - - String serverEnable = environment.getProperty(STARLIGHT_SERVER_ENABLE_KEY); - if (!StringUtils.hasText(serverEnable) || !serverEnable.trim().equalsIgnoreCase(SERVER_ENABLE)) { - return; - } - - Set packagesToScan = new HashSet<>(); - if (importingClassMetadata.hasAnnotation(StarlightScan.class.getName())) { - Map selfBasePackages = - importingClassMetadata.getAnnotationAttributes(StarlightScan.class.getName()); - if (selfBasePackages != null && selfBasePackages.size() > 0) { - packagesToScan.addAll(Arrays.asList((String[]) selfBasePackages.get("basePackages"))); - } - } - - packagesToScan.add(ClassUtils.getPackageName(importingClassMetadata.getClassName())); - - registerRpcServicePostProcessor(packagesToScan, registry); - } - - /** - * Register BeanDefinitionPostProcessor - * - * @param packageToScan - * @param registry - */ - private void registerRpcServicePostProcessor(Set packageToScan, BeanDefinitionRegistry registry) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RpcServicePostProcessor.class); - builder.addConstructorArgValue(packageToScan); - - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); - BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter b/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter deleted file mode 100644 index 94bd2406..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.springcloud.client.outlier.OutlierDetectFilter \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring.factories deleted file mode 100644 index d051df9b..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -com.baidu.formula.config.application.name=cpdinf-starlight-config -com.baidu.formula.config.application.order=1 - diff --git a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 98dafb5f..00000000 --- a/spring-cloud-starter-baidu-starlight/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,6 +0,0 @@ -com.baidu.cloud.starlight.springcloud.client.StarlightClientAutoConfiguration -com.baidu.cloud.starlight.springcloud.server.StarlightServerAutoConfiguration -com.baidu.cloud.starlight.springcloud.server.register.StarlightRegisterAutoConfiguration -com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.StarlightLoadBalancerAutoConfiguration -com.baidu.cloud.starlight.springcloud.lifecycle.StarlightServerLifecycleAutoConfiguration -com.baidu.cloud.starlight.springcloud.lifecycle.StarlightClientLifecycleAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClientTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClientTest.java deleted file mode 100644 index b7155036..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/AbstractClusterClientTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.SpringCloudLoadbalancer; -import com.baidu.cloud.starlight.springcloud.client.properties.ClientConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.configuration.Configuration; -import org.junit.Before; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.DiscoveryClient; - -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.context.ApplicationContext; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Created by liuruisen on 2020/9/21. - */ -@RunWith(MockitoJUnitRunner.class) -public class AbstractClusterClientTest { - - protected LoadBalancerClient loadBalancerClient; - - protected LoadBalancer loadBalancer; - - protected DiscoveryClient discoveryClient; - - protected StarlightClientProperties properties; - - protected List serviceInstances; - - protected ServiceInstance serviceInstance; - - protected SingleStarlightClientManager clientManager; - - protected Configuration configuration; - - protected StarlightRouteProperties routeProperties; - - @Before - public void before() throws IOException { - properties = new StarlightClientProperties(); - ClientConfig defaultConfig = new ClientConfig(); - defaultConfig.setClusterModel(SpringCloudConstants.DEFAULT_CLUSTER_MODEL); - defaultConfig.setCompressType("none"); - defaultConfig.setConnectTimeoutMills(1000); - defaultConfig.setMaxHeartbeatTimes(3); - defaultConfig.setFilters("formularequestdecorate"); - - ClientConfig appConfig = new ClientConfig(); - appConfig.setClusterModel(SpringCloudConstants.DEFAULT_CLUSTER_MODEL); - appConfig.setCompressType("none"); - appConfig.setConnectTimeoutMills(3000); - appConfig.setIoThreadNum(1); - appConfig.setProtocol("brpc"); - appConfig.setMaxHeartbeatTimes(365); - appConfig.setWarmUpCount(1); - appConfig.setWarmUpRatio(100); - appConfig.setFilters(""); - - Map configs = new HashMap(); - configs.put(properties.getDefaultConfig(), defaultConfig); - configs.put("rpc-provider", appConfig); - properties.setConfig(configs); - - serviceInstances = new LinkedList<>(); - serviceInstance = new ServiceInstance() { - @Override - public String getServiceId() { - return "rpc-provider"; - } - - @Override - public String getHost() { - return "localhost"; - } - - @Override - public int getPort() { - return 8899; - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public java.net.URI getUri() { - String uri = "brpc://localhost:8899"; - return java.net.URI.create(uri); - } - - @Override - public Map getMetadata() { - Map metadata = new HashMap<>(); - metadata.put("protocols", "brpc,stargate,springrest"); - return metadata; - } - }; - serviceInstances.add(serviceInstance); - - loadBalancerClient = mock(LoadBalancerClient.class); - loadBalancer = new SpringCloudLoadbalancer(loadBalancerClient); - // doReturn(serviceInstance).when(loadBalancerClient).choose(anyString()); - - discoveryClient = mock(DiscoveryClient.class); - doReturn(serviceInstances).when(discoveryClient).getInstances(anyString()); - - clientManager = SingleStarlightClientManager.getInstance(); - - configuration = mock(Configuration.class); - routeProperties = new StarlightRouteProperties(); - - ApplicationContext applicationContext = mock(ApplicationContext.class); - ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils(); - applicationContextUtils.setApplicationContext(applicationContext); - when(applicationContext.getBean(LoadBalancerClient.class)).thenReturn(loadBalancerClient); - - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClientTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClientTest.java deleted file mode 100644 index 14d60af8..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailFastClusterClientTest.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.service.TestService; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.ServerSocket; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; - -/** - * Created by liuruisen on 2020/3/25. - */ -public class FailFastClusterClientTest extends AbstractClusterClientTest { - - @Test - public void init() { - URI.Builder uriBuilder = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, "localhost", 8888); - SingleStarlightClient starlightClient = Mockito.mock(SingleStarlightClient.class); - doReturn(uriBuilder.build()).when(starlightClient).remoteURI(); - - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient = Mockito.spy(clusterClient); - doReturn(starlightClient).when(clusterClient).initSingleClient(anyString(), anyInt()); - - clusterClient.init(); - } - - @Test - public void initEmptyInstance() throws NoSuchFieldException, IllegalAccessException { - DiscoveryClient discoveryClient = Mockito.mock(DiscoveryClient.class); - doReturn(null).when(discoveryClient).getInstances(anyString()); - - clientManager.destroyAll(); - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient.init(); - Map clientMap = clientManager.allSingleClients(); - assertEquals(clientMap.size(), 0); - } - - @Test - public void refer() throws NoSuchFieldException, IllegalAccessException { - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setProtocol("brpc"); - serviceConfig.setCompressType("none"); - serviceConfig.setFilters(""); - clusterClient.refer(TestService.class, serviceConfig); - // refer twice - clusterClient.refer(TestService.class, serviceConfig); - - Field field = clusterClient.getClass().getSuperclass().getDeclaredField("serviceConfigs"); - field.setAccessible(true); - Map, ServiceConfig> clientMap = (Map, ServiceConfig>) field.get(clusterClient); - - Assert.assertNotNull(clientMap); - assertEquals(clientMap.size(), 1); - assertEquals(clientMap.get(TestService.class), serviceConfig); - } - - @Test - public void request() throws IOException { - SingleStarlightClient starlightClient = Mockito.mock(SingleStarlightClient.class); - - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - ServiceConfig serviceConfig = new ServiceConfig(); - clusterClient.refer(FailFastClusterClient.class, serviceConfig); - clusterClient = Mockito.spy(clusterClient); - doReturn(starlightClient).when(clusterClient).initSingleClient(anyString(), anyInt()); - clusterClient.init(); - - Request request = new RpcRequest(); - request.setServiceClass(FailFastClusterClient.class); - request.setServiceConfig(serviceConfig); - ResultFuture resultFuture = new ResultFuture(); - RpcCallback rpcCallback = new FutureCallback(resultFuture, request); - // return null - doReturn(serviceInstance).when(loadBalancerClient).choose(any()); - doReturn(null).when(loadBalancerClient).execute(any(), any(), any()); - clusterClient.request(request, rpcCallback); - - // exception request - doThrow(new IOException("exception")).when(loadBalancerClient).execute(any(), any(), any()); - clusterClient.request(request, rpcCallback); - try { - resultFuture.get(); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - } - - @Test - public void requestWithEmptyInstance() throws Exception { - LoadBalancerClient loadBalancerClient = Mockito.mock(LoadBalancerClient.class); - doReturn(null).when(loadBalancerClient).choose(anyString()); - - clientManager.destroyAll(); - - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient.init(); - ServiceConfig serviceConfig = new ServiceConfig(); - clusterClient.refer(FailFastClusterClient.class, serviceConfig); - - Request request = new RpcRequest(); - request.setServiceClass(FailFastClusterClient.class); - request.setServiceConfig(serviceConfig); - ResultFuture resultFuture = new ResultFuture(); - RpcCallback rpcCallback = new FutureCallback(resultFuture, request); - // request without instance - try { - clusterClient.request(request, rpcCallback); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - assertEquals(SpringCloudConstants.NO_INSTANCE_ERROR_CODE, ((StarlightRpcException) e).getCode()); - } - - doReturn(serviceInstance).when(loadBalancerClient).choose(anyString()); - clusterClient = Mockito.spy(clusterClient); - SingleStarlightClient starlightClient = Mockito.mock(SingleStarlightClient.class); - doReturn(starlightClient).when(clusterClient).initSingleClient(anyString(), anyInt()); - - Map clientMap = clientManager.allSingleClients(); - - assertEquals(1, clientMap.size()); - } - - @Test - public void destroy() throws NoSuchFieldException, IllegalAccessException { - SingleStarlightClient starlightClient = Mockito.mock(SingleStarlightClient.class); - - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient = Mockito.spy(clusterClient); - doReturn(starlightClient).when(clusterClient).initSingleClient(anyString(), anyInt()); - clusterClient.init(); - - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setProtocol("brpc"); - serviceConfig.setCompressType("none"); - serviceConfig.setFilters(""); - clusterClient.refer(TestService.class, serviceConfig); - - Field field2 = clusterClient.getClass().getSuperclass().getSuperclass().getDeclaredField("serviceConfigs"); - field2.setAccessible(true); - Map, ServiceConfig> serviceConfigMap = (Map, ServiceConfig>) field2.get(clusterClient); - Assert.assertNotNull(serviceConfigMap); - assertEquals(serviceConfigMap.size(), 1); - assertEquals(serviceConfigMap.get(TestService.class), serviceConfig); - - clusterClient.destroy(); - - Assert.assertNotNull(serviceConfigMap); - assertEquals(serviceConfigMap.size(), 0); - } - - @Test - public void destroyWithoutInit() throws NoSuchFieldException, IllegalAccessException { - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient.destroy(); - Field field2 = clusterClient.getClass().getSuperclass().getDeclaredField("serviceConfigs"); - field2.setAccessible(true); - Map, ServiceConfig> serviceConfigMap = (Map, ServiceConfig>) field2.get(clusterClient); - assertEquals(serviceConfigMap.size(), 0); - } - - @Test - public void initSingleClient() throws IOException, NoSuchFieldException, IllegalAccessException { - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setProtocol("brpc"); - serviceConfig.setCompressType("none"); - serviceConfig.setFilters(""); - clusterClient.refer(TestService.class, serviceConfig); - // refer twice - clusterClient.refer(TestService.class, serviceConfig); - - ServerSocket server = new ServerSocket(8899); - SingleStarlightClient starlightClient = clusterClient.initSingleClient("localhost", 8899); - Field field = starlightClient.getClass().getDeclaredField("uri"); - field.setAccessible(true); - URI uri = (URI) field.get(starlightClient); - Assert.assertNotNull(uri); - Assert.assertTrue(uri.getPort() == 8899); - - starlightClient.destroy(); - server.close(); - } - - @Test - public void failFastCallback() throws ExecutionException, InterruptedException { - FailFastClusterClient clusterClient = new FailFastClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - ResultFuture resultFuture = new ResultFuture(); - Request request = new RpcRequest(); - RpcCallback rpcCallback = new FutureCallback(resultFuture, request); - - FailFastClusterClient.FailFastClusterCallback failFastClusterCallback = - clusterClient.new FailFastClusterCallback(rpcCallback); - - Response response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult("Hello"); - - failFastClusterCallback.addTimeout(TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - - } - }, 10, TimeUnit.SECONDS)); - - failFastClusterCallback.onResponse(response); - String result = (String) resultFuture.get(); - assertEquals(result, "Hello"); - - assertEquals(failFastClusterCallback.getRequest(), request); - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClientTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClientTest.java deleted file mode 100644 index c3753420..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/FailOverClusterClientTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import com.baidu.cloud.starlight.springcloud.client.properties.ClientConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.InterfaceConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import org.junit.Test; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/9/21. - */ -public class FailOverClusterClientTest extends AbstractClusterClientTest { - - @Test - public void retryRequest() throws IOException, NoSuchFieldException, IllegalAccessException { - ClientConfig defaultConfig = properties.getClientConfig(properties.getDefaultConfig()); - defaultConfig.setFilters(""); - defaultConfig.setRetryMethods(""); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfig.setRetryMethods("retry"); - interfaceConfig.setRetryTimes(3); - defaultConfig - .setInterfaceConfig(Collections.singletonMap(FailOverClusterClient.class.getName(), interfaceConfig)); - - FailOverClusterClient clusterClient = new FailOverClusterClient("rpc-provider", properties, loadBalancer, - discoveryClient, clientManager, configuration, routeProperties); - clusterClient.init(); - ServiceConfig serviceConfig = new ServiceConfig(); - clusterClient.refer(FailOverClusterClient.class, serviceConfig); - - Request request = new RpcRequest(); - request.setServiceClass(FailOverClusterClient.class); - request.setMethodName("retry"); - request.setServiceConfig(serviceConfig); - ResultFuture resultFuture = new ResultFuture(); - RpcCallback rpcCallback = new FutureCallback(resultFuture, request); - - doReturn(serviceInstance).when(loadBalancerClient).choose(anyString()); - doReturn(null).when(loadBalancerClient).execute(any(), any(), any()); - RpcContext.getContext().setRequestTimeoutMills(3000); - clusterClient.request(request, rpcCallback); - - Class failOverClusterClass = clusterClient.getClass(); - Field remainedRetriesField = failOverClusterClass.getDeclaredField("remainedRetries"); - remainedRetriesField.setAccessible(true); - Map remainedReties = (Map) remainedRetriesField.get(clusterClient); - assertNotNull(remainedReties); - assertEquals(1, remainedReties.size()); - - Field retryTimesMapField = failOverClusterClass.getDeclaredField("retryTimesMap"); - retryTimesMapField.setAccessible(true); - Map retryTimesMap = (Map) retryTimesMapField.get(clusterClient); - assertNotNull(retryTimesMap); - assertEquals(1, retryTimesMap.size()); - - // TODO 如何测试retry能力 - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManagerTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManagerTest.java deleted file mode 100644 index f3705f77..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/SingleStarlightClientManagerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/12/7. - */ -public class SingleStarlightClientManagerTest { - - private static final String HOST = "localhost"; - - private static final Integer PORT = 55555; - - private final TransportConfig transportConfig; - - public SingleStarlightClientManagerTest() { - this.transportConfig = new TransportConfig(); - } - - @Test - public void getSingleClient() { - SingleStarlightClientManager clientManager = SingleStarlightClientManager.getInstance(); - clientManager.removeSingleClient(HOST, PORT); - SingleStarlightClient singleStarlightClient = clientManager.getSingleClient(HOST, PORT); - assertNull(singleStarlightClient); - } - - @Test - public void getOrCreateSingleClient() { - SingleStarlightClientManager clientManager = SingleStarlightClientManager.getInstance(); - SingleStarlightClientManager starlightClientManager = Mockito.spy(clientManager); - SingleStarlightClient singleStarlightClient = Mockito.mock(SingleStarlightClient.class); - doReturn(singleStarlightClient).when(starlightClientManager).createSingleClient(HOST, PORT, transportConfig); - - starlightClientManager.getOrCreateSingleClient(HOST, PORT, transportConfig); - - assertEquals(1, clientManager.allSingleClients().size()); - } - - @Test - public void destroyAll() { - SingleStarlightClientManager clientManager = SingleStarlightClientManager.getInstance(); - SingleStarlightClientManager starlightClientManager = Mockito.spy(clientManager); - - SingleStarlightClient singleStarlightClient = Mockito.mock(SingleStarlightClient.class); - doReturn(true).when(singleStarlightClient).isActive(); - doNothing().when(singleStarlightClient).destroy(); - doReturn(singleStarlightClient).when(starlightClientManager).createSingleClient(HOST, PORT, transportConfig); - - starlightClientManager.getOrCreateSingleClient(HOST, PORT, transportConfig); - - assertEquals(1, starlightClientManager.allSingleClients().size()); - - clientManager.destroyAll(); - - assertEquals(0, starlightClientManager.allSingleClients().size()); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequestTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequestTest.java deleted file mode 100644 index 4c9c31b0..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/StarlightLBRequestTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster; - -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/25. - */ -public class StarlightLBRequestTest { - - @Test - public void apply() { - StarlightClient starlightClient = Mockito.mock(StarlightClient.class); - doNothing().when(starlightClient).request(any(), any()); - StarlightLBRequest starlightLBRequest = new StarlightLBRequest(starlightClient, new RpcRequest(), - new FutureCallback(new ResultFuture(), new RpcRequest())); - try { - starlightLBRequest.apply(null); - } catch (Exception e) { - e.printStackTrace(); - } - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStoreTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStoreTest.java deleted file mode 100644 index 91904d38..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/loadbalance/ServiceInstanceLocalStoreTest.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance; - -import com.baidu.cloud.starlight.springcloud.client.cluster.loadbalance.ServiceInstanceLocalStore; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import org.junit.Test; -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/7/27. - */ -public class ServiceInstanceLocalStoreTest { - - @Test - public void loadLocalCache() { - File file = new File(getCacheFileName("testApp-load")); - if (file.exists()) { - file.delete(); - } - - ServiceInstanceLocalStore localStore = - new ServiceInstanceLocalStore("testApp-load", new StarlightClientProperties()); - - localStore.loadCachedListOfServers(); - - Class lbClass = localStore.getClass(); - - try { - Field cacheFileField = lbClass.getDeclaredField("cacheFile"); - cacheFileField.setAccessible(true); - - Field cacheField = lbClass.getDeclaredField("localSrvListCache"); - cacheField.setAccessible(true); - - assertNotNull(cacheFileField.get(localStore)); - assertTrue(((File) cacheFileField.get(localStore)).exists()); - assertNotNull(cacheField.get(localStore)); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - localStore.close(); - } - - @Test - public void updateLocalCache() { - File file = new File(getCacheFileName("testApp-update")); - if (file.exists()) { - file.delete(); - } - - ServiceInstanceLocalStore localStore = - new ServiceInstanceLocalStore("testApp-update", new StarlightClientProperties()); - - try { - Class lbClass = localStore.getClass(); - Field cacheField = lbClass.getDeclaredField("localSrvListCache"); - cacheField.setAccessible(true); - Properties localCache = (Properties) cacheField.get(localStore); - assertEquals(0, localCache.entrySet().size()); - - List servers = getServiceInstanceList(50000); - - localStore.updateCachedListOfServers(servers); - - Properties localCacheAfter = (Properties) cacheField.get(localStore); - assertEquals(1, localCacheAfter.entrySet().size()); - - localStore.close(); - - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - @Test - public void getLocalCache() { - File file = new File(getCacheFileName("testApp-get")); - if (file.exists()) { - file.delete(); - } - - ServiceInstanceLocalStore localStore = - new ServiceInstanceLocalStore("testApp-get", new StarlightClientProperties()); - - List serverList = localStore.getCachedListOfServers(); - assertEquals(0, serverList.size()); - List servers = getServiceInstanceList(50000); - localStore.updateCachedListOfServers(servers); - - List serverList2 = localStore.getCachedListOfServers(); - assertEquals(50000, serverList2.size()); - - localStore.close(); - } - - @Test - public void createCacheFile() { - ServiceInstanceLocalStore localStore = - new ServiceInstanceLocalStore("testApp-get", new StarlightClientProperties()); - - String filePath = "starlight/test/cache/cache.txt"; - localStore.createCacheFile(filePath); - - assertTrue(new File(filePath).getParentFile().exists()); - assertTrue(new File(filePath).exists()); - - String filePath2 = "starlight/test/cache/cache2.txt"; - localStore.createCacheFile(filePath2); - assertTrue(new File(filePath2).getParentFile().exists()); - assertTrue(new File(filePath2).exists()); - - } - - private String getCacheFileName(String clientName) { - return System.getProperty("java.io.tmpdir") + "/starlight/local-registry/" + clientName + ".cache"; - } - - private List getServiceInstanceList(int size) { - List servers = new ArrayList<>(); - for (int i = 0; i < size; i++) { - - Map labels = new HashMap<>(); - labels.put("EM_PHY_IDC", "idc01"); - labels.put("EM_HOST_NAME", "localhost"); - labels.put("EM_INSTANCE_ID", "instance.test"); - labels.put("EM_PLATFORM", "online"); - labels.put("env", "online"); - labels.put("GRAVITY_CLIENT_VERSION", "2020.0.2-SNAPSHOT"); - labels.put("EM_LOGIC_IDC", "idc"); - labels.put("EM_PRODUCT_LINE", "inf"); - labels.put("MATRIX_HOST_IP", "127.0.0.1"); - labels.put("EPOCH", "1619676145691"); - labels.put("EM_ENV_TYPE", "ONLINE"); - labels.put("protocols", "brpc,stargate,springrest"); - - DefaultServiceInstance serviceInstance = - new DefaultServiceInstance("test-id-" + i, "test-app", "localhost", i, true, labels); - - servers.add(serviceInstance); - } - - return servers; - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelectorTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelectorTest.java deleted file mode 100644 index b4fcaf44..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelClusterSelectorTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label; - -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.junit.Test; -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -/** - * Created by liuruisen on 2021/12/6. - */ -public class LabelClusterSelectorTest { - - @Test - public void filterEndpointsByLabel() { - - String labelSelector = "env=online&&EM_PLATFORM=onlinenew&&EM_LOGIC_IDC=bj"; - - LabelClusterSelector labelService = new LabelClusterSelector(); - labelService.getMeta().put(SpringCloudConstants.LABEL_SELECTOR_ROUTE_KEY, labelSelector); - - long startTime10 = System.currentTimeMillis(); - List result1 = labelService.selectorClusterInstances(serviceInstances(10)); - System.out.println("LabelService filter 10 endpoint cost: " + (System.currentTimeMillis() - startTime10)); - assertEquals(0, result1.size()); - - long startTime500 = System.currentTimeMillis(); - List result2 = labelService.selectorClusterInstances(serviceInstances(500)); - System.out.println("LabelService filter 500 endpoint cost: " + (System.currentTimeMillis() - startTime500)); - assertEquals(0, result2.size()); - - long startTime1000 = System.currentTimeMillis(); - List result3 = labelService.selectorClusterInstances(serviceInstances(1000)); - System.out.println("LabelService filter 1000 endpoint cost: " + (System.currentTimeMillis() - startTime1000)); - assertEquals(0, result3.size()); - - long startTime5000 = System.currentTimeMillis(); - List result4 = labelService.selectorClusterInstances(serviceInstances(5000)); - System.out.println("LabelService filter 5000 endpoint cost: " + (System.currentTimeMillis() - startTime5000)); - assertEquals(0, result4.size()); - - long startTime10000 = System.currentTimeMillis(); - List result5 = labelService.selectorClusterInstances(serviceInstances(10000)); - System.out.println("LabelService filter 10000 endpoint cost: " + (System.currentTimeMillis() - startTime10000)); - assertEquals(0, result5.size()); - - } - - @Test - public void filterEndpointsByLabel2() { - String labelSelector = "env=online&&EM_PLATFORM in (onlinenew,online)"; - - LabelClusterSelector labelService = new LabelClusterSelector(); - labelService.getMeta().put(SpringCloudConstants.LABEL_SELECTOR_ROUTE_KEY, labelSelector); - - long startTime10 = System.currentTimeMillis(); - List result1 = labelService.selectorClusterInstances(serviceInstances(10)); - System.out.println("LabelService filter 10 endpoint cost: " + (System.currentTimeMillis() - startTime10)); - assertEquals(10, result1.size()); - - long startTime500 = System.currentTimeMillis(); - List result2 = labelService.selectorClusterInstances(serviceInstances(500)); - System.out.println("LabelService filter 500 endpoint cost: " + (System.currentTimeMillis() - startTime500)); - assertEquals(500, result2.size()); - - long startTime1000 = System.currentTimeMillis(); - List result3 = labelService.selectorClusterInstances(serviceInstances(1000)); - System.out.println("LabelService filter 1000 endpoint cost: " + (System.currentTimeMillis() - startTime1000)); - assertEquals(1000, result3.size()); - - long startTime5000 = System.currentTimeMillis(); - List result4 = labelService.selectorClusterInstances(serviceInstances(5000)); - System.out.println("LabelService filter 5000 endpoint cost: " + (System.currentTimeMillis() - startTime5000)); - assertEquals(5000, result4.size()); - - long startTime10000 = System.currentTimeMillis(); - List result5 = labelService.selectorClusterInstances(serviceInstances(10000)); - System.out.println("LabelService filter 10000 endpoint cost: " + (System.currentTimeMillis() - startTime10000)); - assertEquals(10000, result5.size()); - - } - - private List serviceInstances(Integer size) { - List endpoints = new ArrayList<>(); - - for (int i = 0; i < size; i++) { - - Map labels = new HashMap<>(); - labels.put("EM_PRODUCT_LINE", "ns"); - labels.put("EM_APP", "service"); - labels.put("env", "online"); - if (i % 2 == 0) { - labels.put("EM_PLATFORM", "online"); - labels.put("EM_LOGIC_IDC", "bj"); - } else { - labels.put("EM_PLATFORM", "onlinenew"); - labels.put("EM_LOGIC_IDC", "nj"); - } - - DefaultServiceInstance endpoint = new DefaultServiceInstance(i + "", "service", "ip." + i, i, true, labels); - - endpoints.add(endpoint); - } - - return endpoints; - } - -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouterTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouterTest.java deleted file mode 100644 index 4f3a7407..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/cluster/route/label/LabelSelectorRouterTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.cluster.route.label; - -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.springcloud.client.cluster.Cluster; -import com.baidu.cloud.starlight.springcloud.client.cluster.LoadBalancer; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightRouteProperties; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Collections; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/12/8. - */ -public class LabelSelectorRouterTest { - - @Test - public void route() { - StarlightRouteProperties routeProperties = new StarlightRouteProperties(); - routeProperties.setEnabled(true); - StarlightRouteProperties.Selector selector = new StarlightRouteProperties.Selector(); - selector.setEnableProviderSelector(true); - selector.setGlobalSelector("env=offline"); - selector.setProviderSelector(Collections.singletonMap("app-a", "EM_PLATFORM in (online,onlinenew)")); - routeProperties.setLabelSelector(selector); - LabelSelectorRouter router = new LabelSelectorRouter("app-a", routeProperties, new StarlightClientProperties(), - Mockito.mock(LoadBalancer.class)); - - RpcRequest request = new RpcRequest(); - request.setServiceName("com.baidu.TestService"); - request.setServiceName("echo"); - - Cluster cluster = router.route(request); - assertNotNull(cluster); - assertTrue(cluster.getClusterSelector() instanceof LabelClusterSelector); - String labelSelector = ((LabelClusterSelector) cluster.getClusterSelector()).getMeta() - .get(SpringCloudConstants.LABEL_SELECTOR_ROUTE_KEY); - assertTrue(labelSelector.contains("env=offline")); - assertTrue(labelSelector.contains("EM_PLATFORM in (online,onlinenew)")); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEventTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEventTest.java deleted file mode 100644 index adbbb521..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectEventTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/9/7. - */ -public class OutlierDetectEventTest { - - @Test - public void outlierReason() { - OutlierDetectEvent event = new OutlierDetectEvent(); - System.out.println(event.outlierReason()); - event.setDetectInterval(3000); - System.out.println(event.outlierReason()); - event.setReqCount(100); - System.out.println(event.outlierReason()); - event.setSuccReqCount(88); - System.out.println(event.outlierReason()); - event.setFailCount(12); - System.out.println(event.outlierReason()); - event.setFailPercent(10); - System.out.println(event.outlierReason()); - event.setDetectFailPercent(60); - System.out.println(event.outlierReason()); - event.setDetectFailCount(66); - System.out.println(event.outlierReason()); - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilterTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilterTest.java deleted file mode 100644 index 2583d2ff..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierDetectFilterTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.statistics.FixedTimeWindowStats; -import com.baidu.cloud.starlight.core.statistics.StarlightStatistics; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.context.ApplicationContext; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Created by liuruisen on 2021/4/25. - */ -@RunWith(MockitoJUnitRunner.class) -public class OutlierDetectFilterTest { - - @Before - public void before() { - SingleStarlightClientManager singleStarlightClientManager = SingleStarlightClientManager.getInstance(); - ApplicationContext applicationContext = mock(ApplicationContext.class); - ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils(); - applicationContextUtils.setApplicationContext(applicationContext); - when(applicationContext.getBean(SingleStarlightClientManager.class)).thenReturn(singleStarlightClientManager); - } - - @Test - public void filterResponse() { - - SingleStarlightClientManager clientManager = - ApplicationContextUtils.getBeanByType(SingleStarlightClientManager.class); - clientManager.getOrCreateSingleClient("localhost", 8888, new TransportConfig()); - SingleStarlightClient singleStarlightClient = clientManager.getSingleClient("localhost", 8888); - - Response response = new RpcResponse(); - Request request = new RpcRequest(); - - OutlierDetectFilter outlierDetectFilter = new OutlierDetectFilter(); - - // remote uri is null - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - URI.Builder builder = new URI.Builder("brpc", "localhost", 8888); - URI remoteURI = builder.build(); - request.setRemoteURI(remoteURI); - - // outlier enabled false - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - // statistics is null - remoteURI = remoteURI.addParameters(SpringCloudConstants.OUTLIER_DETECT_ENABLED_KEY, String.valueOf(true)); - request.setRemoteURI(remoteURI); - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - // outlier stats is null - StarlightStatsManager.getOrCreateStats(remoteURI); - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - // not reach outlier min request - remoteURI = - remoteURI.addParameters(SpringCloudConstants.OUTLIER_DETECT_MINI_REQUEST_NUM_KEY, String.valueOf(3)); - request.setRemoteURI(remoteURI); - StarlightStatistics starlightStatistics = StarlightStatsManager.getStats(remoteURI); - starlightStatistics.registerStats(SpringCloudConstants.OUTLIER_STATS_KEY, new FixedTimeWindowStats(100)); - starlightStatistics.record(request, response); - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - // not reach fail percent - starlightStatistics.record(request, response); - starlightStatistics.record(request, response); - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.ACTIVE, singleStarlightClient.getStatus().getStatus()); - - // outlier - remoteURI = - remoteURI.addParameters(SpringCloudConstants.OUTLIER_DETECT_FAIL_PERCENT_THRESHOLD_KEY, String.valueOf(10)); - request.setRemoteURI(remoteURI); - response.setStatus(1004); - starlightStatistics.record(request, response); - starlightStatistics.record(request, response); - starlightStatistics.record(request, response); - starlightStatistics.record(request, response); - outlierDetectFilter.filterResponse(response, request); - assertEquals(PeerStatus.Status.OUTLIER, singleStarlightClient.getStatus().getStatus()); - - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilterTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilterTest.java deleted file mode 100644 index d7e06813..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/outlier/OutlierEjectServerListFilterTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.outlier; - -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.ClientConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.OutlierConfig; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import org.junit.Test; -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/25. - */ -public class OutlierEjectServerListFilterTest { - - private SingleStarlightClientManager clientManager = SingleStarlightClientManager.getInstance(); - - public List serverList() { - List originalList = new LinkedList<>(); - for (int i = 0; i < 10000; i++) { - DefaultServiceInstance serviceInstance = - new DefaultServiceInstance("id" + i, "test-app", "localhost", 1000 + i, true); - SingleStarlightClient singleClient = clientManager.getOrCreateSingleClient(serviceInstance.getHost(), - serviceInstance.getPort(), new TransportConfig()); - if (i < 2000) { // mark server as outlier - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.OUTLIER, System.currentTimeMillis())); - } - - if (i >= 2000 && i < 4000) { - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, System.currentTimeMillis())); - } - - if (i >= 4000) { - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - } - originalList.add(serviceInstance); - } - - return originalList; - } - - @Test - public void getFilteredList() { - StarlightClientProperties clientProperties = new StarlightClientProperties(); - OutlierConfig outlierConfig = new OutlierConfig(); - outlierConfig.setMaxEjectPercent(90); - outlierConfig.setBaseEjectTime(30); - outlierConfig.setMaxEjectTime(300); - outlierConfig.setEnabled(true); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setOutlier(outlierConfig); - - clientProperties.setConfig(Collections.singletonMap("testApp", clientConfig)); - - OutlierEjectServerListFilter serverListFilter = - new OutlierEjectServerListFilter(clientManager, clientProperties, "testApp"); - - List originalList = serverList(); - // eject all 2000 OUTLIER - List filteredList = serverListFilter.getFilteredList(originalList); - assertEquals(8000, filteredList.size()); - assertNotSame(filteredList, originalList); - - // eject 1000 OUTLIER - outlierConfig.setMaxEjectPercent(10); - List filterList2 = serverListFilter.getFilteredList(originalList); - assertEquals(9000, filterList2.size()); - assertNotSame(filteredList, originalList); - } - - @Test - public void getFilteredListSize1() { - StarlightClientProperties clientProperties = new StarlightClientProperties(); - OutlierConfig outlierConfig = new OutlierConfig(); - outlierConfig.setMaxEjectPercent(90); - outlierConfig.setBaseEjectTime(30); - outlierConfig.setMaxEjectTime(300); - outlierConfig.setEnabled(true); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setOutlier(outlierConfig); - - clientProperties.setConfig(Collections.singletonMap("testApp", clientConfig)); - - OutlierEjectServerListFilter serverListFilter = - new OutlierEjectServerListFilter(clientManager, clientProperties, "testApp"); - - DefaultServiceInstance server = new DefaultServiceInstance("id", "test-app", "localhost", 20000, true); - List originalList = new LinkedList<>(); - originalList.add(server); - originalList.add(new DefaultServiceInstance("id", "test-app", "localhost", 10000, true)); - SingleStarlightClient singleClient = - clientManager.getOrCreateSingleClient(server.getHost(), server.getPort(), new TransportConfig()); - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.OUTLIER, System.currentTimeMillis())); - - // eject zero OUTLIER - List filteredList = serverListFilter.getFilteredList(originalList); - assertEquals(1, filteredList.size()); - assertNotSame(filteredList, originalList); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfigTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfigTest.java deleted file mode 100644 index 56410432..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/ClientConfigTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/12/10. - */ -public class ClientConfigTest { - - @Test - public void getRequestTimeoutMills() { - ClientConfig clientConfig = new ClientConfig(); - assertNull(clientConfig.getRequestTimeoutMills(ClientConfigTest.class.getName())); - - clientConfig.setRequestTimeoutMills(100); - - assertEquals(new Integer(100), clientConfig.getRequestTimeoutMills(ClientConfigTest.class.getName())); - - Map interfaceConfigMap = new HashMap<>(); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfig.setRequestTimeoutMills(200); - interfaceConfigMap.put(ClientConfigTest.class.getName(), interfaceConfig); - clientConfig.setInterfaceConfig(interfaceConfigMap); - - assertEquals(new Integer(200), clientConfig.getRequestTimeoutMills(ClientConfigTest.class.getName())); - } - - @Test - public void getRetryTimes() { - ClientConfig clientConfig = new ClientConfig(); - assertNull(clientConfig.getRetryTimes(ClientConfigTest.class.getName())); - - clientConfig.setRetryTimes(1); - - assertEquals(new Integer(1), clientConfig.getRetryTimes(ClientConfigTest.class.getName())); - - Map interfaceConfigMap = new HashMap<>(); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfig.setRetryTimes(2); - interfaceConfigMap.put(ClientConfigTest.class.getName(), interfaceConfig); - clientConfig.setInterfaceConfig(interfaceConfigMap); - - assertEquals(new Integer(2), clientConfig.getRetryTimes(ClientConfigTest.class.getName())); - } - - @Test - public void getRetryMethods() { - - ClientConfig clientConfig = new ClientConfig(); - assertNull(clientConfig.getRetryMethods(ClientConfigTest.class.getName())); - - clientConfig.setRetryMethods("retry"); - - assertEquals("retry", clientConfig.getRetryMethods(ClientConfigTest.class.getName())); - - Map interfaceConfigMap = new HashMap<>(); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfig.setRetryMethods("test"); - interfaceConfigMap.put(ClientConfigTest.class.getName(), interfaceConfig); - clientConfig.setInterfaceConfig(interfaceConfigMap); - - assertEquals("test", clientConfig.getRetryMethods(ClientConfigTest.class.getName())); - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfigTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfigTest.java deleted file mode 100644 index cbc9a336..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/OutlierConfigTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/9/13. - */ -public class OutlierConfigTest { - - @Test - public void merge() { - OutlierConfig outlierConfig = new OutlierConfig(); - outlierConfig.setEnabled(true); - outlierConfig.setDetectInterval(60); - outlierConfig.setBaseEjectTime(120); - outlierConfig.setFailureCountThreshold(120); - outlierConfig.setFailurePercentMinRequest(1); - outlierConfig.setMaxEjectTime(600); - assertEquals(true, outlierConfig.getEnabled()); - assertEquals(60, outlierConfig.getDetectInterval().intValue()); - - OutlierConfig config = new OutlierConfig(); - config.setEnabled(false); - config.setDetectInterval(120); - config.setBaseEjectTime(300); - config.setFailureCountThreshold(300); - config.setFailurePercentMinRequest(3); - - outlierConfig.merge(config); - assertEquals(false, outlierConfig.getEnabled()); - assertEquals(120, outlierConfig.getDetectInterval().intValue()); - - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientPropertiesTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientPropertiesTest.java deleted file mode 100644 index 2d9d8766..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/properties/StarlightClientPropertiesTest.java +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.properties; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/3/25. - */ -public class StarlightClientPropertiesTest { - - private StarlightClientProperties clientProperties; - private ClientConfig defaultConfig; - private ClientConfig appConfig; - private Map clientConfigMap; - - @Before - public void before() { - clientProperties = new StarlightClientProperties(); - defaultConfig = new ClientConfig(); - defaultConfig.setClusterModel(SpringCloudConstants.DEFAULT_CLUSTER_MODEL); - defaultConfig.setCompressType("none"); - defaultConfig.setConnectTimeoutMills(1000); - defaultConfig.setMaxHeartbeatTimes(3); - defaultConfig.setFilters("formularequestdecorate"); - - appConfig = new ClientConfig(); - appConfig.setClusterModel(SpringCloudConstants.DEFAULT_CLUSTER_MODEL); - appConfig.setCompressType("none"); - appConfig.setConnectTimeoutMills(3000); - appConfig.setIoThreadNum(1); - appConfig.setProtocol("brpc"); - appConfig.setMaxHeartbeatTimes(365); - appConfig.setWarmUpCount(1); - appConfig.setWarmUpRatio(100); - appConfig.setFilters(""); - appConfig.setWriteTimeoutMills(1000); - appConfig.setReadIdleTimeout(1000); - - clientConfigMap = new HashMap(); - - clientProperties.setConfig(clientConfigMap); - } - - @Test - public void getConfig() { - Assert.assertEquals(clientProperties.getConfig().size(), 0); - } - - @Test - public void getClientConfig() { - clientConfigMap.put(clientProperties.getDefaultConfig(), defaultConfig); - ClientConfig defaultConfig = clientProperties.getClientConfig(clientProperties.getDefaultConfig()); - Assert.assertNull(defaultConfig.getProtocol()); - clientConfigMap.clear(); - } - - @Test - public void getDefaultConfig() { - Assert.assertEquals(clientProperties.getDefaultConfig(), "default"); - } - - @Test - public void transportConfig() { - // default config is null - clientConfigMap.clear(); - clientConfigMap.put("rpc-provider", appConfig); - TransportConfig transportConfig = clientProperties.transportConfig("rpc-provider"); - Assert.assertTrue(transportConfig.getMaxHeartbeatTimes() == 365); - - // app config is null - clientConfigMap.clear(); - clientConfigMap.put(clientProperties.getDefaultConfig(), defaultConfig); - TransportConfig transportConfig2 = clientProperties.transportConfig("rpc-provider"); - Assert.assertTrue(transportConfig2.getMaxHeartbeatTimes() == 3); - - // app config value is null - clientConfigMap.clear(); - clientConfigMap.put(clientProperties.getDefaultConfig(), defaultConfig); - appConfig.setReadIdleTimeout(null); - appConfig.setWriteTimeoutMills(null); - appConfig.setMaxHeartbeatTimes(null); - appConfig.setConnectTimeoutMills(null); - appConfig.setCompressType(null); - clientConfigMap.put("rpc-provider", appConfig); - TransportConfig transportConfig3 = clientProperties.transportConfig("rpc-provider"); - Assert.assertTrue(transportConfig3.getMaxHeartbeatTimes() == 3); - } - - @Test - public void getIoThreadNum() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.DEFAULT_IO_THREADS_VALUE, properties.getIoThreadNum("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setIoThreadNum(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getIoThreadNum("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setIoThreadNum(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getIoThreadNum("Test").intValue()); - } - - @Test - public void getConnectTimeoutMills() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.CONNECT_TIMEOUT_VALUE.intValue(), properties.getConnectTimeoutMills("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setConnectTimeoutMills(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getConnectTimeoutMills("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setConnectTimeoutMills(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getConnectTimeoutMills("Test").intValue()); - } - - @Test - public void getMaxHeartbeatTimes() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.MAX_HEARTBEAT_TIMES_VALUE, properties.getMaxHeartbeatTimes("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setMaxHeartbeatTimes(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getMaxHeartbeatTimes("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setMaxHeartbeatTimes(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getMaxHeartbeatTimes("Test").intValue()); - } - - @Test - public void getWriteTimeoutMills() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.WRITE_TIMEOUT_VALUE.intValue(), properties.getWriteTimeoutMills("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setWriteTimeoutMills(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getWriteTimeoutMills("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setWriteTimeoutMills(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getWriteTimeoutMills("Test").intValue()); - } - - @Test - public void getReadIdleTimeout() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.READ_IDLE_TIMEOUT_VALUE, properties.getReadIdleTimeout("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setReadIdleTimeout(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getReadIdleTimeout("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setReadIdleTimeout(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getReadIdleTimeout("Test").intValue()); - - } - - @Test - public void getRequestTimeoutMills() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.REQUEST_TIMEOUT_VALUE.intValue(), properties.getRequestTimeoutMills("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setRequestTimeoutMills(999); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(999, properties.getRequestTimeoutMills("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setRequestTimeoutMills(888); - clientConfigMap.put("Test", clientConfig); - - assertEquals(888, properties.getRequestTimeoutMills("Test").intValue()); - - } - - @Test - public void getWarmUpRatio() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(SpringCloudConstants.DEFAULT_WARM_UP_RATIO.intValue(), - properties.getWarmUpRatio("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setWarmUpRatio(99); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(99, properties.getWarmUpRatio("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setWarmUpRatio(88); - clientConfigMap.put("Test", clientConfig); - - assertEquals(88, properties.getWarmUpRatio("Test").intValue()); - - } - - @Test - public void getWarmUpCount() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertNull(properties.getWarmUpCount("Test")); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setWarmUpCount(99); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(99, properties.getWarmUpCount("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setWarmUpCount(88); - clientConfigMap.put("Test", clientConfig); - - assertEquals(88, properties.getWarmUpCount("Test").intValue()); - - } - - @Test - public void getChannelType() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.DEFAULT_RPC_CHANNEL_TYPE_VALUE, properties.getChannelType("Test")); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setChannelType("123"); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals("123", properties.getChannelType("Test")); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setChannelType("456"); - clientConfigMap.put("Test", clientConfig); - - assertEquals("456", properties.getChannelType("Test")); - - } - - @Test - public void getMaxConnections() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.MAX_TOTAL_CONNECTIONS.intValue(), properties.getMaxConnections("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setMaxConnections(99); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(99, properties.getMaxConnections("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setMaxConnections(88); - clientConfigMap.put("Test", clientConfig); - - assertEquals(88, properties.getMaxConnections("Test").intValue()); - } - - @Test - public void getMaxIdleConnections() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.MAX_IDLE_CONNECTIONS.intValue(), properties.getMaxIdleConnections("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setMaxIdleConnections(99); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(99, properties.getMaxIdleConnections("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setMaxIdleConnections(88); - clientConfigMap.put("Test", clientConfig); - - assertEquals(88, properties.getMaxIdleConnections("Test").intValue()); - } - - @Test - public void getMinIdleConnections() { - - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.MIN_IDLE_CONNECTIONS.intValue(), properties.getMinIdleConnections("Test").intValue()); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setMinIdleConnections(99); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(99, properties.getMinIdleConnections("Test").intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setMinIdleConnections(88); - clientConfigMap.put("Test", clientConfig); - - assertEquals(88, properties.getMinIdleConnections("Test").intValue()); - } - - @Test - public void getProtocol() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertNull(properties.getProtocol("Test")); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setProtocol("brpc"); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals("brpc", properties.getProtocol("Test")); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setProtocol("stargate"); - clientConfigMap.put("Test", clientConfig); - - assertEquals("stargate", properties.getProtocol("Test")); - - } - - @Test - public void getCompressType() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals("none", properties.getCompressType("Test")); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setCompressType("brpc"); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals("brpc", properties.getCompressType("Test")); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setCompressType("stargate"); - clientConfigMap.put("Test", clientConfig); - - assertEquals("stargate", properties.getCompressType("Test")); - - } - - @Test - public void getFilters() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(SpringCloudConstants.DEFAULT_CLIENT_FILTERS, properties.getFilters("Test")); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setFilters("brpc"); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(SpringCloudConstants.DEFAULT_CLIENT_FILTERS + ",brpc", properties.getFilters("Test")); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setFilters("stargate"); - clientConfigMap.put("Test", clientConfig); - - assertEquals(SpringCloudConstants.DEFAULT_CLIENT_FILTERS + ",stargate", properties.getFilters("Test")); - } - - @Test - public void getRequestTimeoutMills2() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(Constants.REQUEST_TIMEOUT_VALUE, - properties.getRequestTimeoutMills("Test", this.getClass().getName())); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setRequestTimeoutMills(111); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(111, properties.getRequestTimeoutMills("Test", this.getClass().getName()).intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setRequestTimeoutMills(222); - clientConfigMap.put("Test", clientConfig); - - assertEquals(222, properties.getRequestTimeoutMills("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap = new HashMap<>(); - defalutConfig.setInterfaceConfig(interfaceConfigMap); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfigMap.put(this.getClass().getName(), interfaceConfig); - interfaceConfig.setRequestTimeoutMills(333); - - assertEquals(222, properties.getRequestTimeoutMills("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap1 = new HashMap<>(); - clientConfig.setInterfaceConfig(interfaceConfigMap1); - InterfaceConfig config = new InterfaceConfig(); - interfaceConfigMap1.put(this.getClass().getName(), config); - config.setRequestTimeoutMills(444); - assertEquals(444, properties.getRequestTimeoutMills("Test", this.getClass().getName()).intValue()); - } - - @Test - public void getRetryTimes() { - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(SpringCloudConstants.DEFAULT_RETRY_TIMES, - properties.getRetryTimes("Test", this.getClass().getName())); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setRetryTimes(111); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(111, properties.getRetryTimes("Test", this.getClass().getName()).intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setRetryTimes(222); - clientConfigMap.put("Test", clientConfig); - - assertEquals(222, properties.getRetryTimes("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap = new HashMap<>(); - defalutConfig.setInterfaceConfig(interfaceConfigMap); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfigMap.put(this.getClass().getName(), interfaceConfig); - interfaceConfig.setRetryTimes(333); - - assertEquals(222, properties.getRetryTimes("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap1 = new HashMap<>(); - clientConfig.setInterfaceConfig(interfaceConfigMap1); - InterfaceConfig config = new InterfaceConfig(); - interfaceConfigMap1.put(this.getClass().getName(), config); - config.setRetryTimes(444); - assertEquals(444, properties.getRetryTimes("Test", this.getClass().getName()).intValue()); - - } - - @Test - public void getRetryDelayTimeUnitMills() { - - StarlightClientProperties properties = new StarlightClientProperties(); - assertEquals(SpringCloudConstants.DEFAULT_RETRY_DELAY_MILLS, - properties.getRetryDelayTimeUnitMills("Test", this.getClass().getName())); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setRetryDelayTimeUnitMills(111); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals(111, properties.getRetryDelayTimeUnitMills("Test", this.getClass().getName()).intValue()); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setRetryDelayTimeUnitMills(222); - clientConfigMap.put("Test", clientConfig); - - assertEquals(222, properties.getRetryDelayTimeUnitMills("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap = new HashMap<>(); - defalutConfig.setInterfaceConfig(interfaceConfigMap); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfigMap.put(this.getClass().getName(), interfaceConfig); - interfaceConfig.setRetryDelayTimeUnitMills(333); - - assertEquals(222, properties.getRetryDelayTimeUnitMills("Test", this.getClass().getName()).intValue()); - - Map interfaceConfigMap1 = new HashMap<>(); - clientConfig.setInterfaceConfig(interfaceConfigMap1); - InterfaceConfig config = new InterfaceConfig(); - interfaceConfigMap1.put(this.getClass().getName(), config); - config.setRetryDelayTimeUnitMills(444); - assertEquals(444, properties.getRetryDelayTimeUnitMills("Test", this.getClass().getName()).intValue()); - } - - @Test - public void getRetryMethods() { - - StarlightClientProperties properties = new StarlightClientProperties(); - assertNull(properties.getRetryMethods("Test", this.getClass().getName())); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - defalutConfig.setRetryMethods("111"); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - assertEquals("111", properties.getRetryMethods("Test", this.getClass().getName())); - - ClientConfig clientConfig = new ClientConfig(); - clientConfig.setRetryMethods("222"); - clientConfigMap.put("Test", clientConfig); - - assertEquals("222", properties.getRetryMethods("Test", this.getClass().getName())); - - Map interfaceConfigMap = new HashMap<>(); - defalutConfig.setInterfaceConfig(interfaceConfigMap); - InterfaceConfig interfaceConfig = new InterfaceConfig(); - interfaceConfigMap.put(this.getClass().getName(), interfaceConfig); - interfaceConfig.setRetryMethods("333"); - - assertEquals("222", properties.getRetryMethods("Test", this.getClass().getName())); - - Map interfaceConfigMap1 = new HashMap<>(); - clientConfig.setInterfaceConfig(interfaceConfigMap1); - InterfaceConfig config = new InterfaceConfig(); - interfaceConfigMap1.put(this.getClass().getName(), config); - config.setRetryMethods("444"); - assertEquals("444", properties.getRetryMethods("Test", this.getClass().getName())); - - } - - @Test - public void outlierConifg() { - StarlightClientProperties properties = new StarlightClientProperties(); - - Map clientConfigMap = new HashMap<>(); - properties.setConfig(clientConfigMap); - - ClientConfig defalutConfig = new ClientConfig(); - clientConfigMap.put(properties.getDefaultConfig(), defalutConfig); - - ClientConfig appConfiggh = new ClientConfig(); - clientConfigMap.put("starlight-provider", appConfiggh); - - OutlierConfig outlierConfig = new OutlierConfig(); - outlierConfig.setEnabled(true); - outlierConfig.setDetectInterval(60); - outlierConfig.setBaseEjectTime(120); - outlierConfig.setFailureCountThreshold(120); - outlierConfig.setFailurePercentMinRequest(1); - outlierConfig.setMaxEjectTime(600); - defalutConfig.setOutlier(outlierConfig); - assertEquals(true, properties.getOutlierConfig("starlight-provider").getEnabled()); - assertEquals(true, outlierConfig.getEnabled()); - - OutlierConfig config = new OutlierConfig(); - config.setEnabled(false); - config.setDetectInterval(120); - config.setBaseEjectTime(300); - config.setFailureCountThreshold(300); - config.setFailurePercentMinRequest(3); - appConfiggh.setOutlier(config); - assertEquals(false, properties.getOutlierConfig("starlight-provider").getEnabled()); - assertEquals(true, outlierConfig.getEnabled()); - assertEquals(false, config.getEnabled()); - assertEquals(20, properties.getOutlierConfig("starlight-provider").getMaxEjectPercent().intValue()); - - assertEquals(true, properties.getOutlierConfig("starlight-app").getEnabled()); - assertEquals(20, properties.getOutlierConfig("starlight-app").getMaxEjectPercent().intValue()); - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilterTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilterTest.java deleted file mode 100644 index 655575fd..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/client/shutdown/ShutdownServerListFilterTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.client.shutdown; - -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.springcloud.client.cluster.SingleStarlightClientManager; -import com.baidu.cloud.starlight.springcloud.client.properties.StarlightClientProperties; -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import org.junit.Before; -import org.junit.Test; -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/26. - */ -public class ShutdownServerListFilterTest { - - private List originalList; - - private SingleStarlightClientManager clientManager = SingleStarlightClientManager.getInstance(); - - @Before - public void before() { - originalList = new LinkedList<>(); - for (int i = 0; i < 10000; i++) { - long shutdownTime = System.currentTimeMillis(); - DefaultServiceInstance server = null; - if (i < 2000) { // mark server as shutting down, shutdown time > epoch will remove - server = new DefaultServiceInstance(i + "", "testApp", "localhost", 1000 + i, true, - Collections.singletonMap(SpringCloudConstants.EPOCH_KEY, String.valueOf(shutdownTime - 10))); - SingleStarlightClient singleClient = - clientManager.getOrCreateSingleClient(server.getHost(), server.getPort(), new TransportConfig()); - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, shutdownTime)); - } - - if (i >= 2000 && i < 4000) { // mark server as shutdown, shutdown time < epoch will not remove - server = new DefaultServiceInstance(i + "", "testApp", "localhost", 1000 + i, true, - Collections.singletonMap(SpringCloudConstants.EPOCH_KEY, String.valueOf(shutdownTime + 10))); - SingleStarlightClient singleClient = - clientManager.getOrCreateSingleClient(server.getHost(), server.getPort(), new TransportConfig()); - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.SHUTDOWN, shutdownTime)); - } - - if (i >= 4000) { - server = new DefaultServiceInstance(i + "", "testApp", "localhost", 1000 + i, true, - Collections.singletonMap(SpringCloudConstants.EPOCH_KEY, String.valueOf(shutdownTime - 10))); - SingleStarlightClient singleClient = - clientManager.getOrCreateSingleClient(server.getHost(), server.getPort(), new TransportConfig()); - singleClient.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - } - originalList.add(server); - } - - } - - @Test - public void getFilteredList() { - ShutdownServerListFilter shutdownServerListFilter = - new ShutdownServerListFilter(clientManager, new StarlightClientProperties()); - - List filteredList = shutdownServerListFilter.getFilteredList(originalList); - assertEquals(8000, filteredList.size()); - assertNotSame(filteredList, originalList); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtilsTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtilsTest.java deleted file mode 100644 index 3dab54d9..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/ApplicationContextUtilsTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.contrib.java.lang.system.EnvironmentVariables; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.Environment; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Created by liuruisen on 2020/3/26. - */ -@RunWith(MockitoJUnitRunner.class) -public class ApplicationContextUtilsTest { - private Environment environment; - - private ApplicationContext applicationContext; - - @Before - public void before() { - environment = mock(Environment.class); - applicationContext = mock(ApplicationContext.class); - ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils(); - applicationContextUtils.setApplicationContext(applicationContext); - when(applicationContext.getEnvironment()).thenReturn(environment); - when(applicationContext.getBean(String.class)).thenReturn("123"); - when(environment.getProperty("spring.main.web-application-type")).thenReturn("none"); - } - - @Test - public void getBeanByType() { - assertEquals(ApplicationContextUtils.getBeanByType(String.class), "123"); - - assertEquals(ApplicationContextUtils.getBeanByType(null), null); - } - - @Test - public void getApplicationContext() { - assertEquals(ApplicationContextUtils.getApplicationContext(), applicationContext); - } - - @Test - public void getEnvironment() { - assertEquals(ApplicationContextUtils.getEnvironment(), environment); - } - - @Test - public void getServerPortFromServerPort() { - StarlightServerProperties properties = new StarlightServerProperties(); - when(applicationContext.getBean(StarlightServerProperties.class)).thenReturn(properties); - when(environment.getProperty(SpringCloudConstants.SERVER_PORT_KEY, "8080")).thenReturn("8888"); - assertEquals(Integer.valueOf(8888), ApplicationContextUtils.getServerPort()); - } - - @Test - public void getServerPortFromStarlightProperties() { - StarlightServerProperties properties = new StarlightServerProperties(); - properties.setPort(8866); - when(applicationContext.getBean(StarlightServerProperties.class)).thenReturn(properties); - when(environment.getProperty(SpringCloudConstants.SERVER_PORT_KEY, "8888")).thenReturn("8888"); - assertEquals(Integer.valueOf(8866), ApplicationContextUtils.getServerPort()); - } - - @Test(expected = IllegalArgumentException.class) - public void getServerPortError() { - StarlightServerProperties properties = new StarlightServerProperties(); - when(applicationContext.getBean(StarlightServerProperties.class)).thenReturn(properties); - when(environment.getProperty("spring.main.web-application-type")).thenReturn("servlet"); - ApplicationContextUtils.getServerPort(); - } - - @Rule - public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); - - @Test - public void getAppNameFromStarlightName() { - - when(environment.getProperty(SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY)).thenReturn("starlight-name"); - - assertEquals("starlight-name", ApplicationContextUtils.getApplicationName()); - } - - @Test - public void getAppNameFromEmApp() { - environmentVariables.set(SpringCloudConstants.EM_APP, "em-name"); - environmentVariables.set(SpringCloudConstants.EM_PLATFORM, "em-platform"); - environmentVariables.set(SpringCloudConstants.EM_PRODUCT_LINE, "em-product"); - - doReturn(null).when(environment).getProperty(SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY); - - assertEquals("em-name", ApplicationContextUtils.getApplicationName()); - } - - @Test - public void getAppNameFromSpringName() { - environmentVariables.set(SpringCloudConstants.EM_APP, "em-name"); - - doReturn(null).when(environment).getProperty(SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY); - - doReturn("spring-name").when(environment).getProperty(SpringCloudConstants.SPRING_APPLICATION_NAME_KEY); - - assertEquals("spring-name", ApplicationContextUtils.getApplicationName()); - - } - - @Test - public void getAppNameFromDefault() { - environmentVariables.set(SpringCloudConstants.EM_APP, null); - - doReturn(null).when(environment).getProperty(SpringCloudConstants.STARLIGHT_SERVER_NAME_KEY); - - doReturn(null).when(environment).getProperty(SpringCloudConstants.SPRING_APPLICATION_NAME_KEY); - - assertEquals("application", ApplicationContextUtils.getApplicationName()); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/XdsUtilsTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/XdsUtilsTest.java deleted file mode 100644 index f1387296..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/common/XdsUtilsTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.common; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/11/8. - */ -public class XdsUtilsTest { - - @Test - public void convertedInstanceId() { - - String instanceId = "1.idc"; - String expectId = "1-online-idc"; - - assertEquals(expectId, RouteUtils.convertedInstanceId(instanceId)); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerApp.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerApp.java deleted file mode 100644 index fadb7de3..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerApp.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server; - -import com.baidu.cloud.starlight.springcloud.server.annotation.StarlightScan; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration; - -@SpringBootApplication(exclude = {ConsulServiceRegistryAutoConfiguration.class}) -@StarlightScan -public class StarlightServerApp { - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfigurationTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfigurationTest.java deleted file mode 100644 index 828778e7..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/StarlightServerAutoConfigurationTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server; - -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.core.rpc.RpcServiceRegistry; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * Created by liuruisen on 2020/3/26. - */ -@RunWith(SpringRunner.class) -@SpringBootTest(value = {"spring.cloud.config.enabled=false", "spring.main.web-application-type=none", - "spring.application.name=provider", "starlight.server.port=8006", "starlight.server.enable=true", - "spring.cloud.consul.discovery.enabled=false", "spring.cloud.consul.discovery.heartbeat.enabled=false", - "spring.cloud.consul.discovery.register=false", "spring.cloud.service-registry.enabled=false", - "spring.cloud.service-registry.auto-registration.enabled=false", "starlight.server.name=rpc-provider", - "starlight.server.host=0.0.0.0", "spring.cloud.gravity.enabled=false", - "spring.cloud.gravity.serverUrl=localhost:7777"}, classes = StarlightServerApp.class) -public class StarlightServerAutoConfigurationTest { - - @Autowired - private StarlightServerAutoConfiguration serverAutoConfiguration; - - @Autowired - private StarlightServer starlightServer; - - @Test - public void starlightServer() { - Assert.assertNotNull(serverAutoConfiguration); - Assert.assertNotNull(starlightServer); - RpcServiceRegistry serviceRegistry = RpcServiceRegistry.getInstance(); - Assert.assertEquals(serviceRegistry.rpcServices().size(), 2 + 1); // + 1 HeartBeatService - } - -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/filter/TestFilter.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/filter/TestFilter.java deleted file mode 100644 index 034bb328..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/filter/TestFilter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.filter; - -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class TestFilter implements Filter { - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerPropertiesTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerPropertiesTest.java deleted file mode 100644 index f86bd05b..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/properties/StarlightServerPropertiesTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.properties; - -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/25. - */ -public class StarlightServerPropertiesTest { - - private StarlightServerProperties properties; - - @Before - public void before() { - properties = new StarlightServerProperties(); - properties.setProtocols("brpc"); - properties.setAcceptThreadNum(1); - properties.setAllIdleTimeout(100); - properties.setCompressType("none"); - properties.setFilters(""); - properties.setHost("localhost"); - properties.setIoThreadNum(8); - properties.setName("rpc-provider"); - properties.setPort(8005); - properties.setWriteTimeoutMills(3000); - } - - @Test - public void serverProperties() { - Assert.assertEquals(properties.getProtocols(), "brpc"); - Assert.assertEquals(properties.getAcceptThreadNum(), Integer.valueOf(1)); - Assert.assertEquals(properties.getAllIdleTimeout(), Integer.valueOf(100)); - Assert.assertEquals(properties.getCompressType(), "none"); - Assert.assertEquals(properties.getFilters(), ""); - Assert.assertEquals(properties.getHost(), "localhost"); - Assert.assertEquals(properties.getIoThreadNum(), Integer.valueOf(8)); - Assert.assertEquals(properties.getName(), "rpc-provider"); - Assert.assertEquals(properties.getPort(), Integer.valueOf(8005)); - Assert.assertEquals(properties.getWriteTimeoutMills(), Integer.valueOf(3000)); - } - - @Test - public void transportConfig() { - TransportConfig transportConfig = properties.transportConfig(); - Assert.assertEquals(transportConfig.getIoThreadNum(), Integer.valueOf(8)); - Assert.assertEquals(transportConfig.getWriteTimeoutMills(), Integer.valueOf(3000)); - Assert.assertEquals(transportConfig.getAllIdleTimeout(), Integer.valueOf(100)); - Assert.assertEquals(transportConfig.getAcceptThreadNum(), Integer.valueOf(1)); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListenerTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListenerTest.java deleted file mode 100644 index f28fb765..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/StarlightRegisterListenerTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register; - -import com.baidu.cloud.starlight.springcloud.common.SpringCloudConstants; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.cloud.client.serviceregistry.Registration; -import org.springframework.context.ApplicationContext; - -import java.util.Map; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/12/7. - */ -public class StarlightRegisterListenerTest { - - @Test - public void starlightMetas() { - - StarlightRegisterListener registerListener = new StarlightRegisterListener() { - @Override - protected Registration createStarlightRegistration() { - return null; - } - }; - - StarlightServerProperties properties = new StarlightServerProperties(); - properties.setPort(8006); - properties.setProtocols("brpc"); - - registerListener.applicationContext = Mockito.mock(ApplicationContext.class); - doReturn(properties).when(registerListener.applicationContext).getBean(StarlightServerProperties.class); - - Map starlightMetas = registerListener.starlightMetas(); - - assertEquals(3, starlightMetas.size()); - assertNotNull(starlightMetas.get(SpringCloudConstants.EPOCH_KEY)); - assertNotNull(starlightMetas.get(SpringCloudConstants.INTERFACES_KEY)); - assertNotNull(starlightMetas.get(SpringCloudConstants.INTERFACES_KEY)); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListenerTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListenerTest.java deleted file mode 100644 index 287267ce..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/consul/StarlightConsulRegisterListenerTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.consul; - -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import com.ecwid.consul.v1.agent.model.NewService; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.cloud.client.serviceregistry.Registration; -import org.springframework.cloud.client.serviceregistry.ServiceRegistry; -import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties; -import org.springframework.cloud.consul.discovery.HeartbeatProperties; -import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration; -import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; - -import java.lang.reflect.Field; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/3/26. - */ -@RunWith(MockitoJUnitRunner.class) -public class StarlightConsulRegisterListenerTest { - - private StarlightConsulRegisterListener consulRegisterListener; - - private ApplicationStartedEvent applicationEvent; - - private ConsulDiscoveryProperties discoveryProperties; - - private HeartbeatProperties heartbeatProperties; - - private ConfigurableEnvironment environment; - - @Before - public void before() throws NoSuchFieldException, IllegalAccessException { - consulRegisterListener = new StarlightConsulRegisterListener(); - - environment = Mockito.mock(ConfigurableEnvironment.class); - doReturn("rpc-provider").when(environment).getProperty("starlight.server.name", "starlight-server"); - doReturn("instanceId").when(environment).getProperty("spring.cloud.consul.discovery.instanceId", "instanceId"); - - ServiceRegistry serviceRegistry = Mockito.mock(ServiceRegistry.class); - doNothing().when(serviceRegistry).register(any()); - doNothing().when(serviceRegistry).deregister(any()); - - discoveryProperties = Mockito.mock(ConsulDiscoveryProperties.class); - doReturn("localhost").when(discoveryProperties).getHostname(); - doReturn("1s").when(discoveryProperties).getHealthCheckInterval(); - doReturn("1223").when(discoveryProperties).getHealthCheckTimeout(); - doReturn("2312").when(discoveryProperties).getHealthCheckCriticalTimeout(); - doReturn(true).when(discoveryProperties).getHealthCheckTlsSkipVerify(); - - heartbeatProperties = Mockito.mock(HeartbeatProperties.class); - doReturn(false).when(heartbeatProperties).isEnabled(); - - ConfigurableApplicationContext applicationContext = Mockito.mock(ConfigurableApplicationContext.class); - doReturn(serviceRegistry).when(applicationContext).getBean(ServiceRegistry.class); - doReturn(discoveryProperties).when(applicationContext).getBean(ConsulDiscoveryProperties.class); - doReturn(environment).when(applicationContext).getEnvironment(); - doReturn(heartbeatProperties).when(applicationContext).getBean(HeartbeatProperties.class); - // StarlightServerProperties - StarlightServerProperties properties = new StarlightServerProperties(); - properties.setPort(8006); - doReturn(properties).when(applicationContext).getBean(StarlightServerProperties.class); - - applicationEvent = Mockito.mock(ApplicationStartedEvent.class); - doReturn(applicationContext).when(applicationEvent).getApplicationContext(); - - Field field = consulRegisterListener.getClass().getSuperclass().getDeclaredField("serviceRegistry"); - field.setAccessible(true); - field.set(consulRegisterListener, serviceRegistry); - - Field field2 = consulRegisterListener.getClass().getSuperclass().getDeclaredField("applicationContext"); - field2.setAccessible(true); - field2.set(consulRegisterListener, applicationContext); - - ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils(); - applicationContextUtils.setApplicationContext(applicationContext); - } - - @Test - public void createStarlightRegistration() { - Registration registration = consulRegisterListener.createStarlightRegistration(); - Assert.assertTrue(registration instanceof ConsulRegistration); - - ConsulRegistration consulRegistration = (ConsulRegistration) registration; - Assert.assertEquals(consulRegistration.getHost(), "localhost"); - Assert.assertEquals(consulRegistration.getPort(), 8006); - NewService service = consulRegistration.getService(); - Assert.assertNotNull(service); - } - - @Test - public void createStarlightRegistrationError() { - doReturn("").when(environment).getProperty("starlight.server.name", "starlight-server"); - try { - consulRegisterListener.createStarlightRegistration(); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalArgumentException); - } - - doReturn("-1").when(environment).getProperty("starlight.server.port"); - try { - consulRegisterListener.createStarlightRegistration(); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalArgumentException); - } - - doReturn("rpc-provider").when(environment).getProperty("starlight.server.name", "starlight-server"); - doReturn("8006").when(environment).getProperty("starlight.server.port"); - } - - @Test - public void createStarlightRegistrationFullConfig() { - doReturn(true).when(discoveryProperties).isPreferAgentAddress(); - doReturn("localhost").when(discoveryProperties).getHostname(); - - doReturn(true).when(heartbeatProperties).isEnabled(); - doReturn("3s").when(heartbeatProperties).getTtl(); - - doReturn("").when(discoveryProperties).getHealthCheckCriticalTimeout(); - - Registration registration = consulRegisterListener.createStarlightRegistration(); - Assert.assertTrue(registration instanceof ConsulRegistration); - ConsulRegistration consulRegistration = (ConsulRegistration) registration; - Assert.assertEquals(consulRegistration.getService().getAddress(), null); - Assert.assertEquals(consulRegistration.getPort(), 8006); - NewService service = consulRegistration.getService(); - Assert.assertNotNull(service); - } - - @Test - public void onApplication() { - // consulRegisterListener.onApplicationEvent(applicationEvent); - consulRegisterListener.deRegister(); - } - - @Test - public void deRegister() { - consulRegisterListener.deRegister(); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistrationTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistrationTest.java deleted file mode 100644 index 7c652d36..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/GravityRegistrationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.gravity; - -import org.junit.Test; - -import java.util.Collections; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/8/13. - */ -public class GravityRegistrationTest { - - @Test - public void getServiceId() { - GravityRegistration registration = new GravityRegistration(); - registration.setServiceId("rpc-provider"); - assertEquals("rpc-provider", registration.getServiceId()); - } - - @Test - public void getHost() { - GravityRegistration registration = new GravityRegistration(); - registration.setHost("localhost"); - assertEquals("localhost", registration.getHost()); - } - - @Test - public void getPort() { - GravityRegistration registration = new GravityRegistration(); - registration.setPort(8888); - assertEquals(8888, registration.getPort()); - } - - @Test - public void isSecure() { - GravityRegistration registration = new GravityRegistration(); - assertFalse(registration.isSecure()); - } - - @Test - public void getUri() { - GravityRegistration registration = new GravityRegistration(); - registration.setSchema("rpc"); - registration.setPort(8888); - registration.setHost("127.0.0.1"); - assertTrue(registration.getUri().toASCIIString().contains("rpc://127.0.0.1:8888")); - } - - @Test - public void getMetadata() { - GravityRegistration registration = new GravityRegistration(); - registration.setMetadata(Collections.singletonMap("key", "val")); - assertTrue(registration.getMetadata().size() == 1); - assertEquals(registration.getMetadata().get("key"), "val"); - - } - - @Test - public void getScheme() { - GravityRegistration registration = new GravityRegistration(); - registration.setSchema("rpc"); - assertEquals("rpc", registration.getScheme()); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListenerTest.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListenerTest.java deleted file mode 100644 index 468f260f..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/register/gravity/StarlightGravityRegisterListenerTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.register.gravity; - -import com.baidu.cloud.starlight.springcloud.common.ApplicationContextUtils; -import com.baidu.cloud.starlight.springcloud.server.properties.StarlightServerProperties; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; - -import java.lang.reflect.Field; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/8/11. - */ -public class StarlightGravityRegisterListenerTest { - - private ConfigurableEnvironment environment; - - private StarlightGravityRegisterListener listener; - - @Before - public void before() throws NoSuchFieldException, IllegalAccessException { - listener = new StarlightGravityRegisterListener(); - - // mock environment - environment = Mockito.mock(ConfigurableEnvironment.class); - doReturn("rpc-provider").when(environment).getProperty("starlight.server.name"); - doReturn("instanceId").when(environment).getProperty("spring.cloud.consul.discovery.instanceId", "instanceId"); - doReturn("brpc,stargate,springrest").when(environment).getProperty("starlight.server.protocols"); - - // StarlightServerProperties - StarlightServerProperties properties = new StarlightServerProperties(); - properties.setPort(8006); - - // mock applicationContext - ConfigurableApplicationContext applicationContext = Mockito.mock(ConfigurableApplicationContext.class); - doReturn(environment).when(applicationContext).getEnvironment(); - doReturn(properties).when(applicationContext).getBean(StarlightServerProperties.class); - - // set applicationContext - Field field2 = listener.getClass().getSuperclass().getDeclaredField("applicationContext"); - field2.setAccessible(true); - field2.set(listener, applicationContext); - - ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils(); - applicationContextUtils.setApplicationContext(applicationContext); - } - - @Test - public void createStarlightRegistration() { - GravityRegistration registration = (GravityRegistration) listener.createStarlightRegistration(); - Assert.assertNotNull(registration.getServiceId()); - assertEquals("rpc-provider", registration.getServiceId()); // service - assertEquals("rpc", registration.getScheme()); // schema - assertEquals(8006, registration.getPort()); // port - assertEquals("brpc,stargate,springrest", registration.getMetadata().get("protocols")); - } -} \ No newline at end of file diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoService.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoService.java deleted file mode 100644 index 664ce2a1..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoService.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -/** - * Created by liuruisen on 2020/3/26. - */ -public interface EchoService { - String echo(String message); -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoServiceImpl.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoServiceImpl.java deleted file mode 100644 index 2826999c..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/EchoServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -/** - * Created by liuruisen on 2020/3/26. - */ -@RpcService(filters = "test", protocol = "brpc") -public class EchoServiceImpl implements EchoService { - - @Override - public String echo(String message) { - return "Echo " + message; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestService.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestService.java deleted file mode 100644 index 590e3bee..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestService.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -/** - * Created by liuruisen on 2020/3/25. - */ -public interface TestService { - - String echo(String message); -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestServiceImpl.java b/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestServiceImpl.java deleted file mode 100644 index b0ab0c9d..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/java/com/baidu/cloud/starlight/springcloud/server/service/TestServiceImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.springcloud.server.service; - -import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService; - -/** - * Created by liuruisen on 2020/3/26. - */ -@RpcService -public class TestServiceImpl implements TestService { - @Override - public String echo(String message) { - return "Echo: " + message; - } -} diff --git a/spring-cloud-starter-baidu-starlight/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter b/spring-cloud-starter-baidu-starlight/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter deleted file mode 100644 index 0cabe317..00000000 --- a/spring-cloud-starter-baidu-starlight/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.springcloud.server.filter.TestFilter \ No newline at end of file diff --git a/starlight/pom.xml b/starlight/pom.xml deleted file mode 100644 index ae72e86b..00000000 --- a/starlight/pom.xml +++ /dev/null @@ -1,433 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - pom - ${project.groupId}:${project.artifactId} - Starlight: simple fast rpc framework - - - starlight-api - starlight-protocol - starlight-transport - starlight-core - starlight-serialization - starlight-all - - - - - UTF-8 - 1.8 - - 4.9.10 - 2.0.9 - false - - - - - - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - - - - - - - - junit - junit - 4.13.2 - test - - - - - - com.github.stefanbirkner - system-rules - 1.19.0 - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - ${java.version} - ${java.version} - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.21.0 - - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - true - - - - attach-sources - - jar-no-fork - - verify - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.11.2 - - UTF-8 - - - - - jar - - package - - -Xdoclint:none - - - - - - pl.project13.maven - git-commit-id-plugin - ${git-commit-id-plugin.version} - - true - yyyy-MM-dd'T'HH:mm:ssZ - true - ${project.build.outputDirectory}/git.properties - - - - - revision - - - - - - - - com.github.os72 - protoc-jar-maven-plugin - 3.6.0.1 - - - generate-sources - - run - - generate-sources - - 2.5.0 - none - true - src/main/java - - src/main/proto - - - - - generate-test-sources - - run - - generate-test-sources - - 2.5.0 - true - none - src/test/java - - src/test/proto - - - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.1 - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.1 - - true - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.6.0 - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.apache.maven.plugins - maven-source-plugin - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - - org.apache.maven.plugins - maven-deploy-plugin - - ${skip_maven_deploy} - - - - org.apache.maven.plugins - maven-surefire-plugin - - 1 - false - -Dfile.encoding=UTF-8 -Xms512m -Xmx1024m - - - - - org.codehaus.mojo - cobertura-maven-plugin - - - - - com/baidu/cloud/starlight/benchmark/**/*.class - com/baidu/cloud/starlight/core/benchmark/**/*.class - com/baidu/cloud/starlight/api/exception/*.class - com/baidu/cloud/starlight/api/extension/*.class - org/openjdk/jmh/infra/generated/**/*.class - - - - xml - html - - - true - - - - - com.diffplug.spotless - spotless-maven-plugin - 2.22.1 - - - - resources/baidu-formatter.xml - - - resources/license-header - - - - - UTF-8 - 4 - true - true - true - true - false - false - custom_1 - false - false - - - - - - - apply - - compile - - - - - org.jacoco - jacoco-maven-plugin - 0.8.13 - - - prepare-agent - - prepare-agent - - - - report - - report - - test - - - - - org.apache.maven.plugins - maven-release-plugin - 3.0.1 - - starlight-v@{project.version} - - - - - - https://github.com/baidu/starlight - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - CPD Infra Team - cpd_inf@baidu.com - Baidu - http://www2.baidu.com - - - - scm:git:${project.scm.url} - scm:git:${project.scm.url} - https://github.com/baidu/starlight.git - HEAD - - - - - false - - - true - - ossrh - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - - - - deploy - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.1.0 - - - --pinentry-mode - loopback - - - - - sign-artifacts - - sign - - verify - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ${skip_maven_deploy} - ossrh - https://oss.sonatype.org/ - false - - - - - - - - diff --git a/starlight/resources/baidu-formatter.xml b/starlight/resources/baidu-formatter.xml deleted file mode 100644 index 29d8607d..00000000 --- a/starlight/resources/baidu-formatter.xml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/starlight/resources/license-header b/starlight/resources/license-header deleted file mode 100644 index ea8e99f5..00000000 --- a/starlight/resources/license-header +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - \ No newline at end of file diff --git a/starlight/starlight-all/pom.xml b/starlight/starlight-all/pom.xml deleted file mode 100644 index a1418601..00000000 --- a/starlight/starlight-all/pom.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-all - The all in one project of stargate - - - - com.baidu.cloud - starlight-api - ${project.version} - - - - com.baidu.cloud - starlight-core - ${project.version} - - - - com.baidu.cloud - starlight-transport - ${project.version} - - - - com.baidu.cloud - starlight-serialization - ${project.version} - - - - com.baidu.cloud - starlight-protocol-brpc - ${project.version} - - - - com.baidu.cloud - starlight-protocol-stargate - ${project.version} - - - - com.baidu.cloud - starlight-protocol-http - ${project.version} - - - - - - - - maven-javadoc-plugin - 3.11.2 - - - javadoc-jar - - jar - - package - - true - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.1 - - - - shade - - package - - true - true - - - com.baidu.cloud:starlight-api - com.baidu.cloud:starlight-core - com.baidu.cloud:starlight-transport - com.baidu.cloud:starlight-serialization - com.baidu.cloud:starlight-protocol-brpc - com.baidu.cloud:starlight-protocol-stargate - com.baidu.cloud:starlight-protocol-http - - - - - - - - - - - - - diff --git a/starlight/starlight-api/pom.xml b/starlight/starlight-api/pom.xml deleted file mode 100644 index 235b4a22..00000000 --- a/starlight/starlight-api/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-api - - true - - - - org.slf4j - slf4j-api - 1.7.25 - - - - ch.qos.logback - logback-classic - 1.3.12 - - - - com.baidu.cloud - spring-cloud-baidu-thirdparty-commons - 2024.0.1-SNAPSHOT - - - - diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/Constants.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/Constants.java deleted file mode 100644 index 2d48a48b..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/Constants.java +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.common; - -import com.baidu.cloud.starlight.api.utils.EnvUtils; - -import java.util.regex.Pattern; - -/** - * Created by liuruisen on 2019/12/3. - */ -public class Constants { - - /**** 服务描述和引用 相关参数 ****/ - /** - * URI里指定默认值,比如有key,那么DEFAULT_KEY_PREFIX+key指定的值就是该key的默认值 - */ - public static final String DEFAULT_KEY_PREFIX = "default."; - - /** - * Comma split pattern - */ - public static final Pattern COMMA_SPLIT_PATTERN = Pattern.compile("\\s*[,]+\\s*"); - - /** - * Group key - */ - public static final String GROUP_KEY = "group"; - - /** - * Version key - */ - public static final String VERSION_KEY = "version"; - - /** - * class.getCanonicalName() - */ - public static final String INTERFACE_KEY = "interface"; - - /** - * Rpc Service Key - */ - public static final String SERVICE_KEY = "service"; - - /** - * Connect Timeout key - */ - public static final String CONNECT_TIMEOUT_KEY = "connect_timeout"; - - /** - * Connect Timeout value: millions - */ - public static final Integer CONNECT_TIMEOUT_VALUE = 3000; - - /** - * Write to remote timeout - */ - public static final String WRITE_TIMEOUT_KEY = "write_timeout"; - - /** - * Write to remote timeout: millions - */ - public static final Integer WRITE_TIMEOUT_VALUE = 3000; - - /** - * Request timeout key - */ - public static final String REQUEST_TIMEOUT_KEY = "request_timeout"; - - /** - * Request timeout value: millions, default 30s - */ - public static final Integer REQUEST_TIMEOUT_VALUE = 30 * 1000; - - /** - * Whether to open the connection keep-alive capability - */ - public static final String CONNECT_KEEPALIVE_ENABLED_KEY = "connect_keepalive_enabled"; - - /** - * Default is false - */ - public static final boolean CONNECT_KEEPALIVE_ENABLED_VALUE = false; - - /** - * Read Idle timeout key, used in Client Side - */ - public static final String READ_IDLE_TIMEOUT_KEY = "read_idle_timeout"; - - /** - * Read Idle timeout value - */ - public static final int READ_IDLE_TIMEOUT_VALUE = 60; - - /** - * Max heartbeat times key, Client Side - */ - public static final String MAX_HEARTBEAT_TIMES_KEY = "max_heartbeat_times"; - - /** - * Max heartbeat times - */ - public static final int MAX_HEARTBEAT_TIMES_VALUE = 3; - - /** - * Io Thread Num Key, Used in both side - */ - public static final String IO_THREADS_KEY = "io_thread_num"; - - /** - * Default IO Thread Nums - */ - public static final int DEFAULT_IO_THREADS_VALUE = EnvUtils.getCpuCores(); - - /** - * RPC Channel Type: long \ short \ pool - */ - public static final String RPC_CHANNEL_TYPE_KEY = "channel_type"; - - /** - * Default Rpc Channel type - */ - public static final String DEFAULT_RPC_CHANNEL_TYPE_VALUE = "long"; - - /** - * Unspecified protocol - */ - public static final String UNSPECIFIED_PROTOCOL = "unspecified"; - - /** - * Protocol key - */ - public static final String PROTOCOL_KEY = "protocol"; - - /** - * Accept Thread Num Key, Used in Server side - */ - public static final String ACCEPT_THREADS_KEY = "accept_thread_num"; - - /** - * Default acceptor thread nums - */ - public static final Integer DEFAULT_ACCEPTOR_THREAD_VALUE = 1; - - /** - * Netty Server SO_BACKLOG - */ - public static final Integer SO_BACKLOG = 1024; - - /** - * Netty Server SO_LINGER - */ - public static final Integer SO_LINGER = 5; - - /** - * Netty Server SO_SNDBUF - */ - public static final Integer SO_SNDBUF = 64 * 1024; - - /** - * Netty Server SO_REVBUF - */ - public static final Integer SO_REVBUF = 64 * 1024; - - /** - * All Idle timeout key, used in Server Side - */ - public static final String ALL_IDLE_TIMEOUT_KEY = "all_idle_timeout"; - - /** - * All Idle timeout value - */ - public static final int ALL_IDLE_TIMEOUT_VALUE = READ_IDLE_TIMEOUT_VALUE * 3 + 30; - - /** - * Trace id - */ - public static final String TRACE_ID_KEY = "trace.id"; - - /** - * X_B3_TRACE_ID - */ - public static final String X_B3_TRACE_ID = "X-B3-TraceId"; - - /** - * span id - */ - public static final String SPAN_ID_KEY = "span.id"; - - /** - * X_B3_SPAN_ID - */ - public static final String X_B3_SPAN_ID = "X-B3-SpanId"; - - /** - * parent span id - */ - public static final String PARENT_SPAN_ID_KEY = "parent.span.id"; - - /** - * request id - */ - public static final String REQUEST_ID_KEY = "request.id"; - - /** - * Association ID for multi-level calls - */ - public static final String SESSION_ID_KEY = "session.id"; - - /** - * Default thread pool size - */ - public static final Integer DEFAULT_BIZ_THREAD_POOL_SIZE = Math.min(EnvUtils.getCpuCores() + 1, 32); - - /** - * max biz work thread num key, used in both side - */ - public static final String MAX_BIZ_WORKER_NUM_KEY = "max_biz_work_num"; - - /** - * Default max thread pool size - */ - public static final Integer DEFAULT_MAX_BIZ_THREAD_POOL_SIZE = 500; - - /** - * Idle thread keep alive time, second - */ - public static final Integer IDlE_THREAD_KEEP_ALIVE_SECOND = 60; - - /** - * Max runnable queue size, used in thread pool - */ - public static final Integer MAX_RUNNABLE_QUEUE_SIZE = 1024; - - /** - * Default server filters - */ - public static final String DEFAULT_SERVER_FILTERS = "servercontext,generic,servermonitor"; - - /** - * Default client filters - */ - public static final String DEFAULT_CLIENT_FILTERS = "clientcontext,clientmonitor"; - - /** - * Uri filters key - */ - public static final String FILTERS_KEY = "filters"; - - /** - * Filter name split key - */ - public static final String FILTER_NAME_SPLIT_KEY = ","; - - /** - * Transport factory name - */ - public static final String DEFAULT_TRANSPORT_FACTORY_NAME = "starlight"; - - /** - * Return Success - */ - public static final Integer SUCCESS_CODE = 200; - - /** - * BRPC Value - */ - public static final String BRPC_VALUE = "brpc"; - - /** - * Any host - */ - public static final String ANYHOST_VALUE = "0.0.0.0"; - - /** - * Pooled channel max connections key - */ - public static final String MAX_TOTAL_CONNECTIONS_KEY = "max_connections"; - - /** - * Pooled channel max connections - */ - public static final Integer MAX_TOTAL_CONNECTIONS = 8; - - /** - * Pooled channel max idle connections key - */ - public static final String MAX_IDLE_CONNECTIONS_KEY = "max_idle_connections"; - - /** - * Pooled channel max idle connections - */ - public static final Integer MAX_IDLE_CONNECTIONS = 8; - - /** - * Pooled channel min idle connections key - */ - public static final String MIN_IDLE_CONNECTIONS_KEY = "min_idle_connections"; - - /** - * Pooled channel min idle connections - */ - public static final Integer MIN_IDLE_CONNECTIONS = 2; - - /** - * Pooled channel time between eviction run mills key TODO 可配置 - */ - public static final String TIME_BETWEEN_EVICTION_RUN_MILLS_KEY = "time_between_eviction_run_mills"; - - /** - * Pooled channel time between eviction run mills TODO 可配置 - */ - public static final Integer TIME_BETWEEN_EVICTION_RUN_MILLS = 5 * 60 * 1000; - - /** - * Generic method name - */ - public static final String GENERIC_METHOD_NAME_PREFIX = "$invoke"; - - /** - * is Generic key - */ - public static final String IS_GENERIC_KEY = "is_generic"; - - /** - * The Constant LOCALHOST. - */ - public static final String LOCALHOST_VALUE = "127.0.0.1"; - - /** - * Generic Key, used in stargate protocol support Starlight Client TO generic call TO stargate server - */ - public static final String GENERIC_KEY = "generic"; - - /** - * Stargate uuid, used in stargate protocol support stargate Client TO call TO starlight server - */ - public static final String STARGATE_UUID = "stargate.id"; - - /** - * Starlight server support protocols - */ - public static final String SERVER_PROTOCOLS = "brpc,stargate,springrest"; - - /** - * Used to store thread classloader - */ - public static final String LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY = "thread.classloader"; - - public static final String EM_LOGIC_IDC = "EM_LOGIC_IDC"; - /** - * Jarvis platform environment variables: EM_APP - */ - public static final String EM_APP = "EM_APP"; - - /** - * Jarvis platform environment variables: EM_PRODUCT_LINE - */ - public static final String EM_PRODUCT_LINE = "EM_PRODUCT_LINE"; - - /** - * Jarvis platform environment variables: EM_PLATFORM - */ - public static final String EM_PLATFORM = "EM_PLATFORM"; - - /** - * Jarvis platform environment variables: EM_CPU_CORES - */ - public static final String EM_CPU_CORES = "EM_CPU_CORES"; - - /** - * Jarvis platform environment variables: EM_THREAD_NUMBER - */ - public static final String EM_THREAD_NUMBER = "EM_THREAD_NUMBER"; - - /** - * Jarvis platform environment variables: EM_INSTANCE_ID - */ - public static final String EM_INSTANCE_ID = "EM_INSTANCE_ID"; - - public static final String EM_ENV_TYPE = "EM_ENV_TYPE"; - - public static final String MATRIX_HOST_IP = "MATRIX_HOST_IP"; - - public static final String EM_IP = "EM_IP"; - - public static final String RECONNECTED_TIMES_KEY = "reconnected_times"; - - public static final Integer MAX_RECONNECT_TIMES = 3; - - public static final Integer RECONNECT_RETRY_INTERVAL_AFTER_FAILED = 10; // 10s - - /** - * RpcChannel protocol attribute key - */ - public static final String PROTOCOL_ATTR_KEY = PROTOCOL_KEY; - - /** - * Gracefully shutdown quiet period key - */ - public static final String GRACEFULLY_SHUTDOWN_QUIET_PERIOD_KEY = "gracefully_shutdown_quiet_time"; - - /** - * Gracefully shutdown quiet period value: 2s - */ - public static final Integer GRACEFULLY_SHUTDOWN_QUIET_PERIOD_VALUE = 2; - - /** - * Gracefully shutdown timeout key - */ - public static final String GRACEFULLY_SHUTDOWN_TIMEOUT_KEY = "gracefully_shutdown_timeout"; - - /** - * Gracefully shutdown timeout value: 30s - */ - public static final Integer GRACEFULLY_SHUTDOWN_TIMEOUT_VALUE = 30; - - /** - * If enable gracefully shutdown - */ - public static final String GRACEFULLY_SHUTDOWN_ENABLE_KEY = "gracefully_shutdown"; - - /** - * Enable gracefully shutdown - */ - public static final Boolean GRACEFULLY_SHUTDOWN_ENABLE = true; - - /** - * Default compress type - */ - public static final String COMPRESS_TYPE = "none"; - - public static final String RECEIVE_BYTE_MSG_TIME_KEY = "receive_byte_msg_time"; - - /** - * BEFORE_XXXX: Maybe used to troubleshoot - */ - public static final String BEFORE_DECODE_HEADER_TIME_KEY = "before_decode_header_time"; - - public static final String DECODE_HEADER_COST = "decode_header_cost"; - - public static final String BEFORE_DECODE_BODY_TIME_KEY = "before_decode_body_time"; - - public static final String DECODE_BODY_COST = "decode_body_cost"; - - public static final String BEFORE_ENCODE_HEADER_TIME_KEY = "before_encode_header_time"; - - public static final String ENCODE_HEADER_COST = "encode_header_cost"; - - public static final String BEFORE_ENCODE_BODY_TIME_KEY = "before_encode_body_time"; - - public static final String ENCODE_BODY_COST = "encode_body_cost"; - - /** - * server side, before execute method - */ - public static final String BEFORE_EXECUTE_METHOD_TIME_KEY = "before_execute_method_time"; - - /** - * server side, execute method cost - */ - public static final String EXECUTE_METHOD_COST = "execute_method_cost"; - - public static final String BEFORE_CLIENT_REQUEST_TIME_KEY = "before_client_request_time"; - - public static final String CLIENT_REQUEST_COST = "client_request_cost"; - - public static final String REMOTE_ADDRESS_KEY = "remote_address"; - - public static final String BEFORE_THREAD_EXECUTE_TIME_KEY = "before_thread_execute_time"; - - public static final String WAIT_FOR_THREAD_COST = "wait_for_thread_cost"; - - public static final String BEFORE_IO_THREAD_EXECUTE_TIME_KEY = "before_io_thread_execute_time"; - - /** - * 等待IO线程执行的耗时 - */ - public static final String WAIT_FOR_IO_THREAD_COST_KEY = "wait_for_io_thread_cost"; - - public static final String BEFORE_SERVER_FILTER_EXEC_TIME_KEY = "before_server_filter_exec_time"; - - /** - * Server Filter的执行耗时 - */ - public static final String SERVER_FILTER_EXEC_COST_KEY = "server_filter_exec_cost"; - - /** - * client side, before server execute time - */ - public static final String BEFORE_SERVER_EXECUTE_TIME_KEY = "before_call_server_time"; - - /** - * server side, the time when server had handle all one request processes and return response - */ - public static final String RETURN_RESPONSE_TIME_KEY = "end_request_time"; - - /** - * Brpc msg : meta proto2 body proto2 - */ - public static final String PROTO2_STD_MODE = "pb2-std"; - - /** - * Brpc msg : meta proto2 body preserve null - */ - public static final String PROTO2_JAVA_MODE = "pb2-java"; - - public static final String SERIALIZER_MODE_KEY = "serialize_mode"; - - public static final String SERVLET_REQUEST_KEY = "http_servlet_request"; - - public static final String SERVLET_RESPONSE_KEY = "http_servlet_response"; - - /** - * 集群模式下,服务端的应用名称,用于日志记录 - */ - public static final String PROVIDER_APP_NAME_KEY = "provider_app_name"; - - /** - * 集群模式下,consumer的应用名称,用于日志记录 - */ - public static final String CONSUMER_APP_NAME_KEY = "consumer_app_name"; - - /** - * Heartbeat ping - */ - public static final String PING = "PING"; - - /** - * Heartbeat pong - */ - public static final String PONG = "PONG"; - - /** - * Default value of heartbeat request time out :3000ms - */ - public static final Integer HEARTBEAT_REQUEST_TIMEOUT = 3000; - - /** - * Server side: the cost of server exec rpc request( for logging) - */ - public static final String SERVER_EXEC_COST_KEY = "serv_exec_cost"; - - /** - * Server side: the timestamp of server recv req(for logging) - */ - public static final String SERVER_RECEIVE_REQ_TIME_KEY = "serv_recv_req_time"; - - /** - * Netty io ratio key - */ - public static final String NETTY_IO_RATIO_KEY = "netty_ioratio"; - - /** - * Default value of netty io ratio - */ - public static final int DEFAULT_NETTY_IO_RATIO = 100; - - public static final String STARGATE_SESSION_ID_KEY = "stargate.sid"; - - public static final String STARGATE_REQUEST_ID_KEY = "stargate.rid"; - - /** - * sse call back attribute key - */ - public static final String SSE_CALLBACK_ATTR_KEY = "sse_callback"; - - /** - * sse embedded channel attribute key - */ - public static final String SSE_EMBEDDED_CHANNEL_KEY = "sse_embedded_channel"; - - /** - * sse call back request id - */ - public static final String SSE_REQUEST_ID_KEY = "sse_requset_id"; -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/URI.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/URI.java deleted file mode 100644 index 792e966e..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/common/URI.java +++ /dev/null @@ -1,865 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.common; - -import com.baidu.cloud.starlight.api.utils.CollectionUtils; -import com.baidu.cloud.starlight.api.utils.NetUriUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; - -import java.io.UnsupportedEncodingException; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 替换java.net.URI 线程安全 - */ -public final class URI { - - private final String protocol; - - private final String username; - - private final String password; - - private final String host; - - private final int port; - - private final String path; - - private final Map parameters; - - private final Map numbers = new ConcurrentHashMap(); - - // cache - private final transient String ip; - - private final transient String fullString; - - private final transient String identityString; - - private final transient String parameterString; - - private final transient String string; - - public static class Builder { - private final String protocol; - - private final String host; - - private final int port; - - private String username; - - private String password; - - private String path; - - private Map parameters = new HashMap(); - - public Builder(String protocol, String host, int port) { - this.protocol = protocol; - this.host = host; - this.port = port; - } - - public Builder(URI uri) { - this.protocol = uri.getProtocol(); - this.host = uri.getHost(); - this.port = uri.getPort(); - this.username = uri.getUsername(); - this.password = uri.getPassword(); - this.path = uri.getPath(); - this.parameters.putAll(uri.getParameters()); // 返回的是UnmodifiableMap - } - - public Builder(String uri) { - this(valueOf(uri)); - } - - public Builder path(String path) { - this.path = path; - return this; - } - - public Builder username(String username) { - this.username = username; - return this; - } - - public Builder password(String password) { - this.password = password; - return this; - } - - public Builder params(String... pairs) { - this.parameters.putAll(CollectionUtils.toStringMap(pairs)); - return this; - } - - public Builder params(Map parameters) { - this.parameters.putAll(parameters); - return this; - } - - public Builder param(String key, boolean value) { - return param(key, String.valueOf(value)); - } - - public Builder param(String key, int value) { - return param(key, String.valueOf(value)); - } - - public Builder param(String key, long value) { - return param(key, String.valueOf(value)); - } - - public Builder param(String key, double value) { - return param(key, String.valueOf(value)); - } - - public Builder param(String key, Enum value) { - if (value == null) { - return this; - } - return param(key, String.valueOf(value)); - } - - public Builder param(String key, Number value) { - if (value == null) { - return this; - } - return param(key, String.valueOf(value)); - } - - public Builder param(String key, String value) { - if (key == null || key.length() == 0 || value == null || value.length() == 0) { - return this; - } - this.parameters.put(key, value); - return this; - } - - public Builder paramString(String query) { - if (query == null || query.length() == 0) { - return this; - } - return params(NetUriUtils.parseQueryString(query)); - } - - public Builder paramAndEncoded(String key, String value) { - if (value == null || value.length() == 0) { - return this; - } - return param(key, encode(value)); - } - - public Builder paramIfAbsent(String key, String value) { - if (key == null || key.length() == 0 || value == null || value.length() == 0) { - return this; - } - String oldValue = parameters.get(key); - if (oldValue == null || value.length() == 0) { - oldValue = parameters.get(Constants.DEFAULT_KEY_PREFIX + key); - } - if (oldValue != null && oldValue.length() > 0) { - return this; // has param - } - this.parameters.put(key, value); - return this; - } - - public URI build() { - return new URI(this); - } - } - - public URI(Builder builder) { - this(builder.protocol, builder.username, builder.password, builder.host, builder.port, builder.path, - builder.parameters); - } - - public URI(String protocol, String username, String password, String host, int port, String path, - Map parameters) { - if ((username == null || username.length() == 0) && password != null && password.length() > 0) { - throw new IllegalArgumentException("Invalid uri, password without username!"); - } - this.protocol = protocol; - this.username = username; - this.password = password; - this.host = host; - this.port = (port < 0 ? 0 : port); - - // trim the beginning "/" - while (path != null && path.startsWith("/")) { - path = path.substring(1); - } - this.path = path; - if (parameters == null) { - parameters = new HashMap(); - } else { - parameters = new HashMap(parameters); - } - this.parameters = Collections.unmodifiableMap(parameters); - - // build cache - parameterString = buildParameters(); - identityString = buildString(true); - fullString = identityString + (parameterString.length() > 0 ? '?' + parameterString : ""); - // no username and passwd - string = buildString(false) + (parameterString.length() > 0 ? '?' + parameterString : ""); - ip = NetUriUtils.getIpByHost(host); - } - - /** - * Parse uri string - * - * @param uri URL string - * @return URI instance - */ - public static URI valueOf(String uri) { - if (uri == null || (uri = uri.trim()).length() == 0) { - throw new IllegalArgumentException("uri == null"); - } - String protocol = null; - String username = null; - String password = null; - String host = null; - int port = 0; - String path = null; - Map parameters = null; - int i = uri.indexOf("?"); // seperator between body and parameters - if (i >= 0) { - String[] parts = uri.substring(i + 1).split("\\&"); - parameters = new HashMap(); - for (String part : parts) { - part = part.trim(); - if (part.length() > 0) { - int j = part.indexOf('='); - if (j >= 0) { - parameters.put(part.substring(0, j), part.substring(j + 1)); - } else { - parameters.put(part, part); - } - } - } - uri = uri.substring(0, i); - } - i = uri.indexOf("://"); - if (i >= 0) { - if (i == 0) { - throw new IllegalStateException("uri missing protocol: \"" + uri + "\""); - } - protocol = uri.substring(0, i); - uri = uri.substring(i + 3); - } else { - // case: file:/path/to/file.txt - i = uri.indexOf(":/"); - if (i >= 0) { - if (i == 0) { - throw new IllegalStateException("uri missing protocol: \"" + uri + "\""); - } - protocol = uri.substring(0, i); - uri = uri.substring(i + 1); - } - } - - i = uri.indexOf("/"); - if (i >= 0) { - path = uri.substring(i + 1); - uri = uri.substring(0, i); - } - i = uri.indexOf("@"); - if (i >= 0) { - username = uri.substring(0, i); - int j = username.indexOf(":"); - if (j >= 0) { - password = username.substring(j + 1); - username = username.substring(0, j); - } - uri = uri.substring(i + 1); - } - i = uri.indexOf(":"); - if (i >= 0 && i < uri.length() - 1) { - port = Integer.parseInt(uri.substring(i + 1)); - uri = uri.substring(0, i); - } - if (uri.length() > 0) { - host = uri; - } - return new URI(protocol, username, password, host, port, path, parameters); - } - - public String getProtocol() { - return protocol; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - public String getHost() { - return host; - } - - public String getIp() { - return ip; - } - - public int getPort() { - return port; - } - - public String getAddress() { - return port <= 0 ? host : host + ":" + port; - } - - public String getPath() { - return path; - } - - public String getAbsolutePath() { - if (path != null && !path.startsWith("/")) { - return "/" + path; - } - return path; - } - - public URI resetPath(String path) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public URI resetHost(String host) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public URI resetPort(int port) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public URI resetProtocol(String protocol) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public URI resetUsername(String username) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public URI resetPassword(String password) { - return new URI(protocol, username, password, host, port, path, getParameters()); - } - - public Map getParameters() { - return parameters; - } - - public String getParameterAndDecoded(String key) { - return getParameterAndDecoded(key, null); - } - - public String getParameterAndDecoded(String key, String defaultValue) { - return decode(getParameter(key, defaultValue)); - } - - /* - * 根据key获取参数值,如果不存在值,则去取default.key表示的值 - */ - public String getParameter(String key) { - String value = parameters.get(key); - if (value == null || value.length() == 0) { - value = parameters.get(Constants.DEFAULT_KEY_PREFIX + key); - } - return value; - } - - public String getParameter(String key, String defaultValue) { - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - return value; - } - - public String[] getParameter(String key, String[] defaultValue) { - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - return Constants.COMMA_SPLIT_PATTERN.split(value); - } - - public double getParameter(String key, double defaultValue) { - Number n = numbers.get(key); - if (n != null) { - return n.doubleValue(); - } - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - double d = Double.parseDouble(value); - numbers.put(key, d); - return d; - } - - public long getParameter(String key, long defaultValue) { - Number n = numbers.get(key); - if (n != null) { - return n.longValue(); - } - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - long l = Long.parseLong(value); - numbers.put(key, l); - return l; - } - - public int getParameter(String key, int defaultValue) { - Number n = numbers.get(key); - if (n != null) { - return n.intValue(); - } - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - int i = Integer.parseInt(value); - numbers.put(key, i); - return i; - } - - public boolean getParameter(String key, boolean defaultValue) { - String value = getParameter(key); - if (value == null || value.length() == 0) { - return defaultValue; - } - return Boolean.parseBoolean(value); - } - - public double getPositiveParameter(String key, double defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - double value = getParameter(key, defaultValue); - if (value <= 0) { - return defaultValue; - } - return value; - } - - public long getPositiveParameter(String key, long defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - long value = getParameter(key, defaultValue); - if (value <= 0) { - return defaultValue; - } - return value; - } - - public int getPositiveParameter(String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - int value = getParameter(key, defaultValue); - if (value <= 0) { - return defaultValue; - } - return value; - } - - public boolean hasParameter(String key) { - String value = getParameter(key); - return value != null && value.length() > 0; - } - - public String getMethodParameterAndDecoded(String method, String key) { - return URI.decode(getMethodParameter(method, key)); - } - - public String getMethodParameterAndDecoded(String method, String key, String defaultValue) { - return URI.decode(getMethodParameter(method, key, defaultValue)); - } - - public String getMethodParameter(String method, String key) { - String value = parameters.get(method + "." + key); - if (value == null || value.length() == 0) { - return getParameter(key); - } - return value; - } - - public String getMethodParameter(String method, String key, String defaultValue) { - String value = getMethodParameter(method, key); - if (value == null || value.length() == 0) { - return defaultValue; - } - return value; - } - - public double getMethodParameter(String method, String key, double defaultValue) { - String methodKey = method + "." + key; - Number n = numbers.get(methodKey); - if (n != null) { - return n.intValue(); - } - String value = getMethodParameter(method, key); - if (value == null || value.length() == 0) { - return defaultValue; - } - double d = Double.parseDouble(value); - numbers.put(methodKey, d); - return d; - } - - public long getMethodParameter(String method, String key, long defaultValue) { - String methodKey = method + "." + key; - Number n = numbers.get(methodKey); - if (n != null) { - return n.intValue(); - } - String value = getMethodParameter(method, key); - if (value == null || value.length() == 0) { - return defaultValue; - } - long l = Long.parseLong(value); - numbers.put(methodKey, l); - return l; - } - - public int getMethodParameter(String method, String key, int defaultValue) { - String methodKey = method + "." + key; - Number n = numbers.get(methodKey); - if (n != null) { - return n.intValue(); - } - String value = getMethodParameter(method, key); - if (value == null || value.length() == 0) { - return defaultValue; - } - int i = Integer.parseInt(value); - numbers.put(methodKey, i); - return i; - } - - public boolean getMethodParameter(String method, String key, boolean defaultValue) { - String value = getMethodParameter(method, key); - if (value == null || value.length() == 0) { - return defaultValue; - } - return Boolean.parseBoolean(value); - } - - public boolean hasMethodParameter(String method, String key) { - if (method == null) { - String suffix = "." + key; - for (String fullKey : parameters.keySet()) { - if (fullKey.endsWith(suffix)) { - return true; - } - } - return false; - } - if (key == null) { - String prefix = method + "."; - for (String fullKey : parameters.keySet()) { - if (fullKey.startsWith(prefix)) { - return true; - } - } - return false; - } - String value = getMethodParameter(method, key); - return value != null && value.length() > 0; - } - - /** - * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构建的使用Builder进行 - * - * @param parameters - * @return - */ - public URI addParameters(Map parameters) { - if (parameters == null || parameters.size() == 0) { - return this; - } - Map map = new HashMap(getParameters()); - map.putAll(parameters); - return new URI(protocol, username, password, host, port, path, map); - } - - /** - * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构建的使用Builder进行 - * - * @param pairs - * @return - */ - public URI addParameters(String... pairs) { - return addParameters(CollectionUtils.toStringMap(pairs)); - } - - /** - * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构造的使用Builder进行 - * - * @param query - * @return - */ - public URI addParameterString(String query) { - if (query == null || query.length() == 0) { - return this; - } - return addParameters(NetUriUtils.parseQueryString(query)); - } - - /** - * 拷贝构造,仅提供参数全集的方式构建,单个参数逐步构造的使用Builder进行 调换一下顺序,以老的参数覆盖新的参数 - * - * @param parameters - * @return - */ - public URI addParametersIfAbsent(Map parameters) { - if (parameters == null || parameters.size() == 0) { - return this; - } - Map map = new HashMap(parameters); - map.putAll(getParameters()); - return new URI(protocol, username, password, host, port, path, map); - } - - public URI removeParameter(String key) { - if (key == null || key.length() == 0) { - return this; - } - return removeParameters(key); - } - - public URI removeParameters(Collection keys) { - if (keys == null || keys.size() == 0) { - return this; - } - return removeParameters(keys.toArray(new String[0])); - } - - public URI removeParameters(String... keys) { - if (keys == null || keys.length == 0) { - return this; - } - Map map = new HashMap(getParameters()); - for (String key : keys) { - map.remove(key); - } - if (map.size() == getParameters().size()) { - return this; - } - return new URI(protocol, username, password, host, port, path, map); - } - - public URI clearParameters() { - return new URI(protocol, username, password, host, port, path, new HashMap()); - } - - @Override - public String toString() { - return string; - } - - public String toIdentityString() { - return identityString; - } - - public String toFullString() { - return fullString; - } - - public String toParameterString() { - return parameterString; - } - - private String buildParameters() { - StringBuilder buf = new StringBuilder(); - if (getParameters() != null && getParameters().size() > 0) { - boolean first = true; - for (Map.Entry entry : new TreeMap(getParameters()).entrySet()) { - if (entry.getKey() != null && entry.getKey().length() > 0) { - if (first) { - first = false; - } else { - buf.append("&"); - } - buf.append(entry.getKey()); - buf.append("="); - buf.append(entry.getValue() == null ? "" : entry.getValue().trim()); - } - } - } - return buf.toString(); - } - - private String buildString(boolean u) { - StringBuilder buf = new StringBuilder(); - if (protocol != null && protocol.length() > 0) { - buf.append(protocol); - buf.append("://"); - } - if (u && username != null && username.length() > 0) { - buf.append(username); - if (password != null && password.length() > 0) { - buf.append(":"); - buf.append(password); - } - buf.append("@"); - } - if (host != null && host.length() > 0) { - buf.append(host); - if (port > 0) { - buf.append(":"); - buf.append(port); - } - } - if (path != null && path.length() > 0) { - buf.append("/"); - buf.append(path); - } - return buf.toString(); - } - - public java.net.URL toJavaURL() { - try { - return new java.net.URL(toFullString()); - } catch (MalformedURLException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public InetSocketAddress toInetSocketAddress() { - return new InetSocketAddress(host, port); - } - - public String getServiceKey() { - String inf = getServiceName(); - if (inf == null) { - return null; - } - StringBuilder buf = new StringBuilder(); - String group = getParameter(Constants.GROUP_KEY); - if (group != null && group.length() > 0) { - buf.append(group).append(":"); - } - buf.append(inf); - String version = getParameter(Constants.VERSION_KEY); - if (version != null && version.length() > 0) { - buf.append(":").append(version); - } - return buf.toString(); - } - - public String getServiceName() { - String serviceName = getParameter(Constants.SERVICE_KEY); - if (StringUtils.isEmpty(serviceName)) { - serviceName = getParameter(Constants.INTERFACE_KEY); - } - return serviceName; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((host == null) ? 0 : host.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + port; - result = prime * result + ((protocol == null) ? 0 : protocol.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - URI other = (URI) obj; - if (host == null) { - if (other.host != null) { - return false; - } - } else if (!host.equals(other.host)) { - return false; - } - if (path == null) { - if (other.path != null) { - return false; - } - } else if (!path.equals(other.path)) { - return false; - } - if (port != other.port) { - return false; - } - if (protocol == null) { - if (other.protocol != null) { - return false; - } - } else if (!protocol.equals(other.protocol)) { - return false; - } - return true; - } - - public static String encode(String value) { - if (value == null || value.length() == 0) { - return ""; - } - try { - return URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - public static String decode(String value) { - if (value == null || value.length() == 0) { - return ""; - } - try { - return URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/CodecException.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/CodecException.java deleted file mode 100644 index dfd384f4..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/CodecException.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.exception; - -/** - * Created by liuruisen on 2020/2/5. - */ -public class CodecException extends RpcException { - - public static final Integer PROTOCOL_ENCODE_EXCEPTION = 3001; - - public static final Integer PROTOCOL_DECODE_EXCEPTION = 3002; - - public static final Integer SERIALIZE_EXCEPTION = 3003; - - public static final Integer DESERIALIZE_EXCEPTION = 3004; - - public static final Integer PROTOCOL_DECODE_NOTMATCH_EXCEPTION = 3005; - - public static final Integer PROTOCOL_DECODE_NOTENOUGHDATA_EXCEPTION = 3006; - - public static final Integer PROTOCOL_INSUFFICIENT_DATA_EXCEPTION = 3011; - - public static final Integer COMPRESS_EXCEPTION = 3007; - - public static final Integer DECOMPRESS_EXCEPTION = 3008; - - public static final Integer BODY_ENCODE_EXCEPTION = 3009; - - public static final Integer BODY_DECODE_EXCEPTION = 3010; - - public CodecException(String message) { - super(message); - } - - public CodecException(Integer code, String message) { - super(code, message); - } - - public CodecException(String message, Throwable cause) { - super(message, cause); - } - - public CodecException(Integer code, String message, Throwable cause) { - super(code, message, cause); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/RpcException.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/RpcException.java deleted file mode 100644 index 7724d754..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/RpcException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.exception; - -/** - * Created by liuruisen on 2020/2/21. - */ -public class RpcException extends RuntimeException { - - private Integer code; - - public RpcException(Integer code, String message, Throwable cause) { - super(message, cause); - this.code = code; - } - - public RpcException(Integer code, String message) { - super(message); - this.code = code; - } - - public RpcException(String message) { - super(message); - } - - public RpcException(String message, Throwable cause) { - super(message, cause); - } - - public Integer getCode() { - return code; - } - - public void setCode(Integer code) { - this.code = code; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/StarlightRpcException.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/StarlightRpcException.java deleted file mode 100644 index 0e323246..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/StarlightRpcException.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.exception; - -import com.baidu.cloud.starlight.api.model.Request; - -/** - * Exceptions during RPC calls will be wrapped as {@link StarlightRpcException} Abstraction of business exception. - * Created by liuruisen on 2019/12/6. - */ -public class StarlightRpcException extends RpcException { - - public static final Integer MSG_NULL_EXCEPTION = 1000; - - public static final Integer SERVICE_NOT_FOUND_EXCEPTION = 1001; - - public static final Integer METHOD_NOT_FOUND_EXCEPTION = 1002; - - public static final Integer BAD_REQUEST = 4003; - - public static final Integer TIME_OUT_EXCEPTION = 1004; - - public static final Integer INTERNAL_SERVER_ERROR = 1005; - - public static final Integer BIZ_ERROR = 1006; - - public static final Integer UNKNOW = 1007; - - public StarlightRpcException(Integer code, String message) { - super(code, message); - } - - public StarlightRpcException(String message) { - super(message); - } - - public StarlightRpcException(String message, Throwable cause) { - super(message, cause); - } - - public StarlightRpcException(Integer code, String message, Throwable cause) { - super(code, message, cause); - } - - public static StarlightRpcException timeoutException(Request request, String remoteUri) { - return new StarlightRpcException(StarlightRpcException.TIME_OUT_EXCEPTION, - "Client call service {" + request.getServiceName() + "} " + "method {" + request.getMethodName() - + "} time out, remote addr " + remoteUri + ". " + "Maybe caused by: " - + "1. Biz method execution timeout(4801). " + "2. Abnormal server instance status(4802). " - + "3. Rpc message delay(4803). " + "4. Unknow reason(4810). "); - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/TransportException.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/TransportException.java deleted file mode 100644 index 322be0b7..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/exception/TransportException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.exception; - -/** - * Transport Exception, Distinguish from Biz Exception {@link StarlightRpcException} Just Throw Used in - * ClientPeer\ServerPeer\RpcHandler Created by liuruisen on 2020/2/5. - */ -public class TransportException extends RpcException { - - public static final Integer CONNECT_EXCEPTION = 2001; - - public static final Integer WRITE_EXCEPTION = 2002; - - public static final Integer BODY_NULL_EXCEPTION = 2003; - - public static final Integer HEARTBEAT_EXCEPTION = 2004; - - public static final Integer RPC_CHANNEL_NULL_EXCEPTION = 2005; - - public static final Integer BIND_EXCEPTION = 2006; - - public static final Integer SHUTTING_DOWN = 2007; - - public TransportException(Integer code, String message, Throwable cause) { - super(code, message, cause); - } - - public TransportException(Integer code, String message) { - super(code, message); - } - - public TransportException(String message) { - super(message); - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoadContext.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoadContext.java deleted file mode 100644 index f6360f13..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoadContext.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -/** - * ClassLoadContext: Migrate from Stargate {@link IClassLoadStrategy#getClassLoader(ClassLoadContext)}. - */ -@SuppressWarnings("rawtypes") -public class ClassLoadContext { - private final Class m_caller; - - /** - * Returns the class representing the caller of {@link ClassLoaderResolver} API. Can be used to retrieve the - * caller's classloader etc (which may be different from the ClassLoaderResolver's own classloader). - */ - public final Class getCallerClass() { - return m_caller; - } - - /** - * This constructor is package-private to restrict instantiation to {@link ClassLoaderResolver} only. - */ - ClassLoadContext(final Class caller) { - m_caller = caller; - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoaderResolver.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoaderResolver.java deleted file mode 100644 index ede6c085..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ClassLoaderResolver.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -/** - * This non-instantiable non-subclassable class acts as the global point for choosing a ClassLoader for dynamic - * class/resource loading at any point in an application. Migrate from Stargate - * - * @see ResourceLoader - * @see IClassLoadStrategy - * @see DefaultClassLoadStrategy - * - */ -@SuppressWarnings("rawtypes") -public abstract class ClassLoaderResolver { - - /** - * This method selects the "best" classloader instance to be used for class/resource loading by whoever calls this - * method. The decision typically involves choosing between the caller's current, thread context, system, and other - * classloaders in the JVM and is made by the {@link IClassLoadStrategy} instance established by the last call to - * {@link #setStrategy}. - * - * @return classloader to be used by the caller ['null' indicates the primordial loader] - */ - public static synchronized ClassLoader getClassLoader() { - final Class caller = getCallerClass(0); - final ClassLoadContext ctx = new ClassLoadContext(caller); - - return s_strategy.getClassLoader(ctx); - } - - /** - * A package-private version of {@link #getClassLoader()} with adjustable caller offset (useful for embedding this - * method in other library classes in this package). - * - * @param callerOffset extra call context depth offset to pass into getCallerClass(). - */ - static synchronized ClassLoader getClassLoader(final int callerOffset) { - final Class caller = getCallerClass(callerOffset); - final ClassLoadContext ctx = new ClassLoadContext(caller); - - return s_strategy.getClassLoader(ctx); - } - - /** - * Gets the current classloader selection strategy setting. - */ - public static synchronized IClassLoadStrategy getStrategy() { - return s_strategy; - } - - /** - * Sets the classloader selection strategy to be used by subsequent calls to {@link #getClassLoader()}. An instance - * of {@link DefaultClassLoadStrategy} is in effect if this method is never called. - * - * @param strategy [may not be null] - * @return previous setting - */ - public static synchronized IClassLoadStrategy setStrategy(final IClassLoadStrategy strategy) { - if (strategy == null) { - throw new IllegalArgumentException("null input: strategy"); - } - final IClassLoadStrategy old = s_strategy; - s_strategy = strategy; - - return old; - } - - /** - * A helper class to get the call context. It subclasses SecurityManager to make getClassContext() accessible. An - * instance of CallerResolver only needs to be created, not installed as an actual security manager. - */ - private static final class CallerResolver extends SecurityManager { - protected Class[] getClassContext() { - return super.getClassContext(); - } - - } - - private ClassLoaderResolver() {} - - /* - * Indexes into the current method call context with a given offset. - */ - - private static Class getCallerClass(final int callerOffset) { - return CALLER_RESOLVER.getClassContext()[CALL_CONTEXT_OFFSET + callerOffset]; - } - - private static IClassLoadStrategy s_strategy; // initialized in - - private static final int CALL_CONTEXT_OFFSET = 3; // may need to change if - // this class is - // redesigned - - private static final CallerResolver CALLER_RESOLVER; // set in - - static { - try { - // this can fail if the current SecurityManager does not allow - // RuntimePermission ("createSecurityManager"): - CALLER_RESOLVER = new CallerResolver(); - } catch (SecurityException se) { - throw new RuntimeException("ClassLoaderResolver: could not create CallerResolver: " + se); - } - - s_strategy = new DefaultClassLoadStrategy(); - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/DefaultClassLoadStrategy.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/DefaultClassLoadStrategy.java deleted file mode 100644 index ab0793f6..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/DefaultClassLoadStrategy.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -/** - * Migrate from Stargate DefaultClassLoadStrategy 默认选择策略,基本可以满足大部分的情况 - */ -public class DefaultClassLoadStrategy implements IClassLoadStrategy { - - public ClassLoader getClassLoader(final ClassLoadContext ctx) { - if (ctx == null) { - throw new IllegalArgumentException("null input: ctx"); - } - final ClassLoader callerLoader = ctx.getCallerClass().getClassLoader(); - final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - - ClassLoader result; - - // if 'callerLoader' and 'contextLoader' are in a parent-child - // relationship, always choose the child: - - if (isChild(contextLoader, callerLoader)) { - result = callerLoader; - } else if (isChild(callerLoader, contextLoader)) { - result = contextLoader; - } else { - // this else branch could be merged into the previous one, - // but I show it here to emphasize the ambiguous case: - result = contextLoader; - } - - final ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); - - // precaution for when deployed as a bootstrap or extension class: - if (isChild(result, systemLoader)) { - result = systemLoader; - } - return result; - } - - /** - * Returns 'true' if 'loader2' is a delegation child of 'loader1' [or if 'loader1'=='loader2']. Of course, this - * works only for classloaders that set their parent pointers correctly. 'null' is interpreted as the primordial - * loader [i.e., everybody's parent]. - */ - private static boolean isChild(final ClassLoader loader1, ClassLoader loader2) { - if (loader1 == loader2) { - return true; - } - if (loader2 == null) { - return false; - } - if (loader1 == null) { - return true; - } - - for (; loader2 != null; loader2 = loader2.getParent()) { - if (loader2 == loader1) { - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ExtensionLoader.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ExtensionLoader.java deleted file mode 100644 index beee33f1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ExtensionLoader.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * SPI ExtensionLoader Created by liuruisen on 2020/2/3. - */ -public class ExtensionLoader { - - private static final Logger LOG = LoggerFactory.getLogger(ExtensionLoader.class); - - private static final String SERVICES_DIR = "META-INF/services/"; - - private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOCATOR = new ConcurrentHashMap<>(); - - private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(); - - private final Class type; - - private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap<>(); - - private final Map> cachedClasses = new HashMap<>(); - - private final ConcurrentMap cachedInstances = new ConcurrentHashMap<>(); - - private Map exceptions = new ConcurrentHashMap<>(); - - @SuppressWarnings("unchecked") - public static ExtensionLoader getInstance(Class type) { - if (type == null) { - throw new IllegalArgumentException("Extension type == null"); - } - ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOCATOR.get(type); - if (loader == null) { - EXTENSION_LOCATOR.putIfAbsent(type, new ExtensionLoader(type)); - loader = (ExtensionLoader) EXTENSION_LOCATOR.get(type); - } - return loader; - } - - private ExtensionLoader(Class type) { - this.type = type; - } - - public String getExtensionName(T extensionInstance) { - return getExtensionName(extensionInstance.getClass()); - } - - public String getExtensionName(Class extensionClass) { - return cachedNames.get(extensionClass); - } - - @SuppressWarnings("unchecked") - public synchronized T getExtension(String name) { - if (name == null) { - throw new IllegalArgumentException("Extension name == null"); - } - Object instance = cachedInstances.get(name); - if (instance == null) { - instance = createExtension(name); - cachedInstances.putIfAbsent(name, instance); - } - return (T) instance; - } - - public boolean hasExtension(String name) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("Extension name == null"); - } - try { - return getExtensionClass(name) != null; - } catch (Throwable t) { - return false; - } - } - - public Set getSupportedExtensions() { - Map> clazzes = getExtensionClasses(); - return Collections.unmodifiableSet(new TreeSet(clazzes.keySet())); - } - - public Set getLoadedExtensions() { - return Collections.unmodifiableSet(new TreeSet(cachedInstances.keySet())); - } - - private IllegalStateException findException(String name) { - for (Map.Entry entry : exceptions.entrySet()) { - if (entry.getKey().toLowerCase().contains(name.toLowerCase())) { - return entry.getValue(); - } - } - StringBuilder buf = - new StringBuilder("No such extension " + type.getName() + " by name " + name + ", possible causes: "); - int i = 1; - for (Map.Entry entry : exceptions.entrySet()) { - buf.append("\r\n("); - buf.append(i++); - buf.append(") "); - buf.append(entry.getKey()); - buf.append(":\r\n"); - buf.append(entry.getValue()); - } - return new IllegalStateException(buf.toString()); - } - - @SuppressWarnings("unchecked") - private T createExtension(String name) { - Class clazz = getExtensionClasses().get(name); - if (clazz == null) { - throw findException(name); - } - try { - T instance = (T) EXTENSION_INSTANCES.get(clazz); - if (instance == null) { - EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); - instance = (T) EXTENSION_INSTANCES.get(clazz); - } - return instance; - } catch (Throwable t) { - throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type - + ") could not be instantiated: " + t.getMessage(), t); - } - } - - private Class getExtensionClass(String name) { - if (type == null) { - throw new IllegalArgumentException("Extension type == null"); - } - if (name == null) { - throw new IllegalArgumentException("Extension name == null"); - } - Class clazz = getExtensionClasses().get(name); - if (clazz == null) { - throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!"); - } - return clazz; - } - - private Map> getExtensionClasses() { - if (cachedClasses.size() == 0) { - synchronized (cachedClasses) { - if (cachedClasses.size() == 0) { - cachedClasses.putAll(loadExtensionClasses()); - } - } - } - return cachedClasses; - } - - private Map> loadExtensionClasses() { - Map> extensionClasses = new HashMap>(); - String fileName = SERVICES_DIR + type.getName(); - try { - Enumeration urls = ResourceLoader.getResources(fileName); - while (urls.hasMoreElements()) { - URL url = urls.nextElement(); - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); - try { - String line = null; - while ((line = reader.readLine()) != null) { - final int ci = line.indexOf('#'); - if (ci >= 0) { - line = line.substring(0, ci); - } - line = line.trim(); - if (line.length() > 0) { - try { - String name = null; - int i = line.indexOf('='); - if (i > 0) { - name = line.substring(0, i).trim(); - line = line.substring(i + 1).trim(); - } - Class clazz = ResourceLoader.loadClass(line); - if (!type.isAssignableFrom(clazz)) { - throw new IllegalStateException("Error when load extension class(interface: " - + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() - + "is not subtype of interface."); - } - if (name == null || name.length() == 0) { - if (clazz.getSimpleName().length() > type.getSimpleName().length() - && clazz.getSimpleName().endsWith(type.getSimpleName())) { - name = clazz.getSimpleName() - .substring(0, - clazz.getSimpleName().length() - type.getSimpleName().length()) - .toLowerCase(); - } else if (clazz.getSimpleName().length() > type.getSimpleName().length() - && clazz.getSimpleName().startsWith(type.getSimpleName())) { - name = clazz.getSimpleName().substring(type.getSimpleName().length()) - .toLowerCase(); - } else { - throw new IllegalStateException("No such extension name for the class " - + clazz.getName() + " in the config " + url); - } - } - if (!cachedNames.containsKey(clazz)) { - cachedNames.put(clazz, name); - } - Class c = extensionClasses.get(name); - if (c == null) { - extensionClasses.put(name, clazz); - } else if (c != clazz) { - throw new IllegalStateException("Duplicate extension " + type.getName() - + " name " + name + " on " + c.getName() + " and " + clazz.getName()); - } - } catch (Throwable t) { - IllegalStateException e = new IllegalStateException( - "Failed to load extension class(interface: " + type + ", class line: " + line - + ") in " + url + ", cause: " + t.getMessage(), - t); - exceptions.put(line, e); - } - } - } - } finally { - reader.close(); - } - } catch (Throwable t) { - LOG.error("Exception when load extension class(interface: " + type + ", class file: " + url - + ") in " + url, t); - } - } - } catch (Throwable t) { - LOG.error( - "Exception when load extension class(interface: " + type + ", description file: " + fileName + ").", t); - } - return extensionClasses; - } - - @Override - public String toString() { - return this.getClass().getName() + "[" + type.getName() + "]"; - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/IClassLoadStrategy.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/IClassLoadStrategy.java deleted file mode 100644 index b7153ec0..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/IClassLoadStrategy.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -/** - * IClassLoadStrategy Migrate from Stargate {@link ClassLoaderResolver} API. - */ -public interface IClassLoadStrategy { - /** - * Selects a classloader based on a given load context. - * - * @see ClassLoaderResolver#getClassLoader() - */ - ClassLoader getClassLoader(ClassLoadContext ctx); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ResourceLoader.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ResourceLoader.java deleted file mode 100644 index 52ae09be..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/extension/ResourceLoader.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; - -/** - * Migrate from Stargate - */ -public class ResourceLoader { - - /** - * @see ClassLoader#loadClass(String) - */ - public static Class loadClass(final String name) throws ClassNotFoundException { - final ClassLoader loader = ClassLoaderResolver.getClassLoader(1); - - return Class.forName(name, false, loader); - } - - /** - * @see ClassLoader#getResource(String) - */ - public static URL getResource(final String name) { - final ClassLoader loader = ClassLoaderResolver.getClassLoader(1); - - if (loader != null) { - return loader.getResource(name); - } else { - return ClassLoader.getSystemResource(name); - } - } - - /** - * @see ClassLoader#getResourceAsStream(String) - */ - public static InputStream getResourceAsStream(final String name) { - final ClassLoader loader = ClassLoaderResolver.getClassLoader(1); - - if (loader != null) { - return loader.getResourceAsStream(name); - } else { - return ClassLoader.getSystemResourceAsStream(name); - } - - } - - /** - * @see ClassLoader#getResources(String) - */ - public static Enumeration getResources(final String name) throws IOException { - final ClassLoader loader = ClassLoaderResolver.getClassLoader(1); - - if (loader != null) { - return loader.getResources(name); - } else { - return ClassLoader.getSystemResources(name); - } - } - - private ResourceLoader() {} - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/filter/Filter.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/filter/Filter.java deleted file mode 100644 index cda831f1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/filter/Filter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.filter; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -/** - * Async Filter Created by liuruisen on 2019/12/5. - */ -public interface Filter { - /** - * Filter Request - * - * @param invoker - * @param request - * @param callback - */ - void filterRequest(Invoker invoker, Request request, RpcCallback callback); - - /** - * Filter async response - * - * @param response - * @param request - */ - void filterResponse(Response response, Request request); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/Heartbeat.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/Heartbeat.java deleted file mode 100644 index 514581a6..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/Heartbeat.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.heartbeat; - -/** - * Created by liuruisen on 2021/4/23. - */ -public class Heartbeat { - - private String message; - - private Long timestamp; - - public Heartbeat(String message) { - this.message = message; - this.timestamp = System.currentTimeMillis(); - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcRequestHolder.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcRequestHolder.java deleted file mode 100644 index c7b99151..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcRequestHolder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.heartbeat; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.RpcRequest; - -/** - * Created by liuruisen on 2021/4/23. - */ -public class HeartbeatRpcRequestHolder { - - public static RpcRequest heartbeatRequest() { - RpcRequest heartbeatRequest = new RpcRequest(); - heartbeatRequest.setServiceName(HeartbeatService.HEART_BEAT_SERVICE_NAME); - heartbeatRequest.setMethodName(HeartbeatService.HEART_BEAT_METHOD_NAME); - heartbeatRequest.setParams(new Object[] {new Heartbeat(Constants.PING)}); - heartbeatRequest.setParamsTypes(new Class[] {Heartbeat.class}); - heartbeatRequest.setProtocolName(Constants.BRPC_VALUE); - heartbeatRequest.setReturnType(Heartbeat.class); - heartbeatRequest.setGenericReturnType(Heartbeat.class); - - return heartbeatRequest; - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcResponseHolder.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcResponseHolder.java deleted file mode 100644 index ab4fa22f..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatRpcResponseHolder.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.heartbeat; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; - -/** - * Created by liuruisen on 2021/4/23. - */ -public class HeartbeatRpcResponseHolder { - - public static RpcResponse heartbeatResponse(RpcRequest heartbeatRequest) { - RpcResponse heartbeatResponse = new RpcResponse(heartbeatRequest.getId()); - heartbeatResponse.setRequest(heartbeatRequest); - heartbeatResponse.setStatus(Constants.SUCCESS_CODE); - heartbeatResponse.setReturnType(Heartbeat.class); - heartbeatResponse.setResult(new Heartbeat(Constants.PONG)); - heartbeatResponse.setProtocolName(heartbeatRequest.getProtocolName()); - heartbeatResponse.setGenericReturnType(Heartbeat.class); - - return heartbeatResponse; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatService.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatService.java deleted file mode 100644 index fe070c9d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatService.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.heartbeat; - -/** - * Heartbeat service Created by liuruisen on 2021/4/23. - */ -public interface HeartbeatService { - - String HEART_BEAT_METHOD_NAME = "heartbeat"; - - String HEART_BEAT_SERVICE_NAME = "com.baidu.cloud.starlight.api.heartbeat.HeartbeatService"; - - /** - * Heartbeat method - * - * @param request - * @return - */ - Heartbeat heartbeat(Heartbeat request); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatServiceImpl.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatServiceImpl.java deleted file mode 100644 index 603af7ba..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/heartbeat/HeartbeatServiceImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.heartbeat; - -import com.baidu.cloud.starlight.api.common.Constants; - -/** - * Created by liuruisen on 2021/4/23. - */ -public class HeartbeatServiceImpl implements HeartbeatService { - - @Override - public Heartbeat heartbeat(Heartbeat request) { - return new Heartbeat(Constants.PONG); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/AbstractMsgBase.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/AbstractMsgBase.java deleted file mode 100644 index 001f1d0e..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/AbstractMsgBase.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import java.lang.reflect.Type; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Created by liuruisen on 2020/2/7. - */ -public abstract class AbstractMsgBase implements MsgBase { - - /** - * Reserve the first 10 bits for special response, such as SHUTTING_DOWN_EVENT - */ - private static final AtomicLong INVOKE_ID = new AtomicLong(10); - - private long id; - - private Map attachmentKv = new LinkedHashMap<>(); - - /** - * 当前依靠GC机制回收,FIXME 是否进行阅后即焚处理 可存储不随rpc调用传递的信息,如用于记录日志或统计的的数据 - */ - private Map noneAdditionKv = new LinkedHashMap<>(); - - private byte[] bodyBytes; - - private Class returnType; - - private boolean heartbeat; - - private int compressType; // default 0: none compress - - private String protocolName; - - private Type genericReturnType; - - public AbstractMsgBase() { - this.id = INVOKE_ID.getAndIncrement(); - } - - public AbstractMsgBase(long id) { - this.id = id; - } - - @Override - public long getId() { - return id; - } - - @Override - public void setId(long id) { - this.id = id; - } - - @Override - public Map getAttachmentKv() { - return attachmentKv; - } - - @Override - public void setAttachmentKv(Map kvMap) { - this.attachmentKv = kvMap; - } - - @Override - public byte[] getBodyBytes() { - return bodyBytes; - } - - @Override - public void setBodyBytes(byte[] bodyBytes) { - this.bodyBytes = bodyBytes; - } - - @Override - public Class getReturnType() { - return returnType; - } - - @Override - public void setReturnType(Class returnType) { - this.returnType = returnType; - } - - @Override - public boolean isHeartbeat() { - return heartbeat; - } - - @Override - public void setHeartbeat(boolean heartbeat) { - this.heartbeat = heartbeat; - } - - @Override - public int getCompressType() { - return compressType; - } - - @Override - public void setCompressType(int compressType) { - this.compressType = compressType; - } - - @Override - public String getProtocolName() { - return protocolName; - } - - @Override - public void setProtocolName(String protocolName) { - this.protocolName = protocolName; - } - - @Override - public Map getNoneAdditionKv() { - return noneAdditionKv; - } - - @Override - public void setNoneAdditionKv(Map kvMap) { - this.noneAdditionKv = kvMap; - } - - @Override - public Type getGenericReturnType() { - return genericReturnType; - } - - @Override - public void setGenericReturnType(Type returnType) { - this.genericReturnType = returnType; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/MsgBase.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/MsgBase.java deleted file mode 100644 index ca7db49d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/MsgBase.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import java.lang.reflect.Type; -import java.util.Map; - -/** - * Created by liuruisen on 2019/12/3. - */ -public interface MsgBase { - - /** - * Get corelationId: framework id - * - * @return - */ - long getId(); - - /** - * Set framework id - * - * @param id - */ - void setId(long id); - - /** - * kv attachment - * - * @return - */ - Map getAttachmentKv(); - - void setAttachmentKv(Map kvMap); - - /** - * body data - * - * @return - */ - byte[] getBodyBytes(); - - void setBodyBytes(byte[] bodyByteBuf); - - /** - * Body data type, used to serializer/deserializer - * - * @return - */ - Class getReturnType(); - - void setReturnType(Class returnType); - - /** - * Whether it is a heartbeat message - * - * @return - */ - boolean isHeartbeat(); - - void setHeartbeat(boolean heartbeat); - - /** - * Compress type - * - * @return - */ - int getCompressType(); - - void setCompressType(int compressType); - - /** - * Get Protocol name, used to decode Get when decoding - * - * @return - */ - String getProtocolName(); - - /** - * Set Protocol name, used to encode Set when making a request Set when decoding - * - * @param protocolName - */ - void setProtocolName(String protocolName); - - /** - * Store kv information for record log, will not send to peer - * - * @return - */ - Map getNoneAdditionKv(); - - /** - * Store kv information for record log, will not send to peer - * - * @param kvMap - */ - void setNoneAdditionKv(Map kvMap); - - /** - * for http decode, TODO 可以精简为只使用这个类型 - * - * @return - */ - Type getGenericReturnType(); - - void setGenericReturnType(Type returnType); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Request.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Request.java deleted file mode 100644 index 5b515f4d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Request.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -/** - * Collection of information used in the request. Will be used to assemble requests of each protocol(brpc http - * stargate...) Created by liuruisen on 2019/12/3. - */ -public abstract class Request extends AbstractMsgBase { - - /** - * Remote uri of the server instance - * - * @return - */ - public abstract URI getRemoteURI(); - - /** - * Remote uri of the server instance - * - * @param remoteURI - */ - public abstract void setRemoteURI(URI remoteURI); - - /** - * Service name of provider service, the value could be - *

    - *
  • ServiceId (brpc crossing-language or generic call)
  • - *
  • interfaceName (default)
  • - *
- * In order to support multi protocol, we unified the data model of serviceName as group:interfaceName:version. - * - * @return - */ - public abstract String getServiceName(); - - public abstract void setServiceName(String serviceName); - - public abstract String getMethodName(); - - public abstract void setMethodName(String methodName); - - public abstract Object[] getParams(); - - public abstract void setParams(Object[] params); - - public abstract Class[] getParamsTypes(); - - public abstract void setParamsTypes(Class[] paramsTypes); - - public Request() { - super(); - } - - public Request(long id) { - super(id); - } - - public abstract Class getServiceClass(); - - public abstract void setServiceClass(Class serviceClass); - - public abstract Method getMethod(); - - public abstract void setMethod(Method targetMethod); - - /** - * IF we can know service obj before {@link com.baidu.cloud.starlight.api.rpc.ServiceRegistry#discover(String)}, use - * service instances for reflection calls directly such as in HttpDecoder - * - * @return - */ - public abstract Object getServiceObj(); - - public abstract void setServiceObj(Object serviceObj); - - /** - * ServiceConfig represent the service metadata: protocol/version/group/serviceId, etc. - * - * @return - */ - public abstract ServiceConfig getServiceConfig(); - - public abstract void setServiceConfig(ServiceConfig serviceConfig); - - public abstract Type[] getGenericParamsTypes(); - - public abstract void setGenericParamsTypes(Type[] genericParamsTypes); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Response.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Response.java deleted file mode 100644 index 530be81a..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Response.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -/** - * Interface of Response Created by liuruisen on 2019/12/3. - */ -public abstract class Response extends AbstractMsgBase { - - public abstract int getStatus(); - - public abstract void setStatus(int status); - - public abstract String getErrorMsg(); - - public abstract void setErrorMsg(String errorMsg); - - public abstract Object getResult(); - - public abstract void setResult(Object result); - - public Response(long id) { - super(id); - } - - public Response() { - super(); - } - - /** - * Save request information to obtain meta information, such as request kvAttachment - * - * @return - */ - public abstract Request getRequest(); - - public abstract void setRequest(Request request); - - /** - * When exception in response is not null, will throw this Exception - * - * @return - */ - public abstract Throwable getException(); - - /** - * Set exception, when exception instanceof RuntimeException will throw - * - * @param exception - */ - public abstract void setException(Throwable exception); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ResultFuture.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ResultFuture.java deleted file mode 100644 index 53b5713d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ResultFuture.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Returned by an async call: Future Created by liuruisen on 2019/12/8. - */ -public class ResultFuture implements Future { - - private CountDownLatch countDownLatch = new CountDownLatch(1); - - private Response response; - - public void putResponse(Response response) { - this.response = response; - countDownLatch.countDown(); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return countDownLatch.getCount() == 0; - } - - @Override - public boolean isDone() { - return response != null; - } - - @Override - public Object get() throws InterruptedException, ExecutionException { - countDownLatch.await(); - return result(); - } - - @Override - public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - countDownLatch.await(timeout, unit); - if (response == null) { // 在限定时间内未返回,则返回TimeoutException - throw new TimeoutException(); - } - return result(); - } - - private Object result() { - if (response.getStatus() != Constants.SUCCESS_CODE) { - if (response.getException() instanceof RuntimeException) { - throw (RuntimeException) response.getException(); - } - throw new StarlightRpcException(response.getStatus(), response.getErrorMsg(), response.getException()); - } - return response.getResult(); - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcRequest.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcRequest.java deleted file mode 100644 index 67b6314c..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcRequest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.utils.StringUtils; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -/** - * Created by liuruisen on 2020/2/6. - */ -public class RpcRequest extends Request { - - private String serviceName; - - private String methodName; - - private Object[] params; - - private Class[] paramsTypes; - - private Class serviceClass; - - private Method method; - - private Object serviceObj; - - private ServiceConfig serviceConfig; // target service config, contains protocol/timeout - - private URI remoteURI; - - private Type[] genericParamsTypes; - - public RpcRequest() { - super(); - } - - public RpcRequest(long id) { - super(id); - } - - @Override - public String getServiceName() { - if (!StringUtils.isBlank(serviceName)) { - return serviceName; - } - - serviceName = serviceConfig.serviceName(serviceClass); - return serviceName; - } - - @Override - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - @Override - public String getMethodName() { - return methodName; - } - - @Override - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - @Override - public Object[] getParams() { - return this.params; - } - - @Override - public void setParams(Object[] params) { - this.params = params; - } - - @Override - public Class[] getParamsTypes() { - return this.paramsTypes; - } - - @Override - public void setParamsTypes(Class[] paramsTypes) { - this.paramsTypes = paramsTypes; - } - - @Override - public Class getServiceClass() { - return this.serviceClass; - } - - @Override - public void setServiceClass(Class serviceClass) { - this.serviceClass = serviceClass; - } - - @Override - public Method getMethod() { - return this.method; - } - - @Override - public void setMethod(Method targetMethod) { - this.method = targetMethod; - } - - @Override - public ServiceConfig getServiceConfig() { - return this.serviceConfig; - } - - @Override - public void setServiceConfig(ServiceConfig serviceConfig) { - this.serviceConfig = serviceConfig; - } - - @Override - public Object getServiceObj() { - return this.serviceObj; - } - - @Override - public void setServiceObj(Object serviceObj) { - this.serviceObj = serviceObj; - } - - @Override - public URI getRemoteURI() { - return remoteURI; - } - - @Override - public void setRemoteURI(URI remoteURI) { - this.remoteURI = remoteURI; - } - - @Override - public Type[] getGenericParamsTypes() { - return genericParamsTypes; - } - - @Override - public void setGenericParamsTypes(Type[] genericParamsTypes) { - this.genericParamsTypes = genericParamsTypes; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("RpcRequest{"); - sb.append("serviceName='").append(serviceName).append('\''); - sb.append(", methodName='").append(methodName).append('\''); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcResponse.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcResponse.java deleted file mode 100644 index 5198cfa8..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/RpcResponse.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -/** - * Created by liuruisen on 2020/2/6. - */ -public class RpcResponse extends Response { - - private int status; - - private String errorMsg; - - private Throwable exception; - - private Object result; - - private Request request; - - public RpcResponse(long id) { - super(id); - } - - public RpcResponse() { - super(); - } - - @Override - public int getStatus() { - return status; - } - - @Override - public void setStatus(int status) { - this.status = status; - } - - @Override - public String getErrorMsg() { - return errorMsg; - } - - @Override - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - @Override - public Object getResult() { - return result; - } - - @Override - public void setResult(Object result) { - this.result = result; - } - - @Override - public Request getRequest() { - return request; - } - - @Override - public void setRequest(Request request) { - this.request = request; - } - - @Override - public Throwable getException() { - return this.exception; - } - - @Override - public void setException(Throwable exception) { - this.exception = exception; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("RpcResponse{"); - sb.append("status=").append(status); - sb.append(", errorMsg='").append(errorMsg).append('\''); - sb.append(", result=").append(result); - sb.append(", request=").append(request); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ShuttingDownEvent.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ShuttingDownEvent.java deleted file mode 100644 index 7fa4708c..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/ShuttingDownEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -/** - * Created by liuruisen on 2020/12/1. - */ -public class ShuttingDownEvent { - - private final String shuttingDown = "SHUTTING_DOWN"; - - private Long shuttingDownTime; - - public ShuttingDownEvent(Long shuttingDownTime) { - this.shuttingDownTime = shuttingDownTime; - } - - public String getShuttingDown() { - return shuttingDown; - } - - public Long getShuttingDownTime() { - return shuttingDownTime; - } - - public void setShuttingDownTime(Long shuttingDownTime) { - this.shuttingDownTime = shuttingDownTime; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Wrapper.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Wrapper.java deleted file mode 100644 index 57f83df1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/model/Wrapper.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -/** - * Used to wrapper multi params. Used when want to support brpc multi-parameter calls and generic calls NOTICE: When - * used in brpc multi-parameter, both of the server and client must be Starlight Created by liuruisen on 2020/2/14. - */ -public class Wrapper { - - private T obj; - - public Wrapper(T obj) { - this.obj = obj; - } - - public T getObj() { - return obj; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/HeartbeatTrigger.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/HeartbeatTrigger.java deleted file mode 100644 index 7685d5ca..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/HeartbeatTrigger.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.protocol; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; - -/** - * Protocol HeartbeatTrigger Provider method to create Heartbeat Request or Response Created by liuruisen on 2019/12/5. - */ -public interface HeartbeatTrigger { - - Request heartbeatRequest(); - - Response heartbeatResponse(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/Protocol.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/Protocol.java deleted file mode 100644 index 3463cd80..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/Protocol.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.protocol; - -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; - -/** - * Created by liuruisen on 2019/11/27. - */ -public interface Protocol { - - ProtocolEncoder getEncoder(); - - ProtocolDecoder getDecoder(); - - HeartbeatTrigger getHeartbeatTrigger(); - - Serializer getSerialize(); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolDecoder.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolDecoder.java deleted file mode 100644 index dfc1a0c2..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolDecoder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.protocol; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; - -/** - * Created by liuruisen on 2019/12/4. - */ -public interface ProtocolDecoder { - - /** - * Decode byte of the Protocol to MsgBase. Parsing protocol only, not parsing body. Execute in io thread. 1. - * Determine the data type: Request or Response 2. Decode the byte to MsgBase 3. Throw CodecException - * - * @param input - * @return - * @throws CodecException - */ - MsgBase decode(DynamicCompositeByteBuf input) throws CodecException; - - /** - * Decode binary body into java params. Decode from MsgBase and save it. - * - * @param msgBase - * @throws CodecException - */ - void decodeBody(MsgBase msgBase) throws CodecException; -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoder.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoder.java deleted file mode 100644 index 42238c7d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoder.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.protocol; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * Created by liuruisen on 2019/12/4. - */ -public interface ProtocolEncoder { - - Logger LOGGER = LoggerFactory.getLogger(ProtocolEncoder.class); - - /** - * Encoding MsgBase into binary data for the protocol. Body encoding will be handed over to method - * {@link #encodeBody(MsgBase)} 1.Determine the data type: Request or Response 2.Encode the MsgBase to ByteBuf - * 3.Throw CodecException - * - * @param input - * @return - * @throws CodecException - */ - ByteBuf encode(MsgBase input) throws CodecException; - - /** - * Encode params to binary body. Get parameters from MsgBase, encode them and save them. Construct and Encode - * - * @param msgBase - * @throws CodecException - */ - void encodeBody(MsgBase msgBase) throws CodecException; - - /** - * Starlight用于满足各种功能,额外向response kv中添加的内容 - * - * @param response - */ - default void addAdditionalRespKv(Response response) { - Map respExtKv = response.getAttachmentKv(); - try { - if (response.getRequest() != null) { - Request request = response.getRequest(); - // server receive req time - Long recvReqTime = request.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY)); - - // 近似值, 因为encode时获取不到最终发送请求的时间,采取encode header的时间 - Long retRespTime = response.getNoneAdditionKv().get(Constants.BEFORE_ENCODE_HEADER_TIME_KEY) == null - ? null : ((Long) response.getNoneAdditionKv().get(Constants.BEFORE_ENCODE_HEADER_TIME_KEY)); - - Long serverExecCost = null; - if (recvReqTime != null && retRespTime != null) { // 近似值 - serverExecCost = retRespTime - recvReqTime; - } - - Long executeMethodCost = request.getNoneAdditionKv().get(Constants.EXECUTE_METHOD_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.EXECUTE_METHOD_COST)); - - Map tidSpid = LogUtils.parseTraceIdSpanId(request); - - // 服务端回传给客户端的kv对不宜过多,框架层不能引入过多payload - respExtKv.put(Constants.SERVER_RECEIVE_REQ_TIME_KEY, recvReqTime); - respExtKv.put(Constants.SERVER_EXEC_COST_KEY, serverExecCost); - respExtKv.put(Constants.EXECUTE_METHOD_COST, executeMethodCost); - respExtKv.put(Constants.TRACE_ID_KEY, tidSpid.get(LogUtils.TCID)); - respExtKv.put(Constants.REQUEST_TIMEOUT_KEY, - request.getAttachmentKv().get(Constants.REQUEST_TIMEOUT_KEY)); - respExtKv.put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, // approx client request time - request.getAttachmentKv().get(Constants.BEFORE_ENCODE_HEADER_TIME_KEY)); - } - } catch (Throwable e) { - LOGGER.warn("generateStarlightRespMeta from response failed, cause by ", e); - } - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ClientInvoker.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ClientInvoker.java deleted file mode 100644 index e7ce5db1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ClientInvoker.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.ClientPeer; - -/** - * Client side Invoker use {@link ClientPeer} to communicate with server. Created by liuruisen on 2019/12/18. - */ -public interface ClientInvoker extends Invoker { - - /** - * Network communication using ClientPeer: default is NettyClient - * - * @return ClientPeer - */ - ClientPeer getClientPeer(); - - /** - * Target interface information represented by ClientInvoker - * - * @return ServiceConfig - */ - ServiceConfig getServiceConfig(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Invoker.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Invoker.java deleted file mode 100644 index cb98ad16..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Invoker.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; - -/** - * Invoker, invoke the rpc call and handle exceptions There are two types: Client and Server. Created by liuruisen on - * 2019/12/18. - */ -public interface Invoker { - /** - * Invoke on the client or server side. Async call. - *

- * Client side Pack and serialize message. Delegate {@link ClientPeer} to implement real communication. - *

- * - *

- * Server side Unpack and deserialize message. Invoke the real method by java reflection. - *

- * - * @param request request message - * @param callback async callback - */ - void invoke(Request request, RpcCallback callback); - - /** - * Destroy itself and clear resources. - * - */ - default void destroy() {} - - /** - * Init the invoker Init ClientPeer TODO ClientPeer init - */ - default void init() {} - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/LocalContext.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/LocalContext.java deleted file mode 100644 index d289162b..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/LocalContext.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * Used to store app ClassLoader for hairuo, currently. Created by liuruisen on 2020/9/15. - */ -public class LocalContext { - - private static final ConcurrentMap CONTEXTS = new ConcurrentHashMap(); - - public static LocalContext getContext(String id) { - LocalContext context = CONTEXTS.get(id); - if (context == null) { - LocalContext newContext = new LocalContext(); - context = CONTEXTS.putIfAbsent(id, newContext); - if (context == null) { - // put succeeded, use new value - context = newContext; - } - } - return context; - } - - private final ConcurrentMap values = new ConcurrentHashMap(); - - @SuppressWarnings("unchecked") - public T get(String key) { - return (T) values.get(key); - } - - public void set(String key, Object value) { - if (value == null) { - values.remove(key); - } else { - values.put(key, value); - } - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Processor.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Processor.java deleted file mode 100644 index 922b9458..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/Processor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; - -/** - * Processor is responsible for processing Service call. Current used in server side.代表IO线程执行结束后的异步调用执行 Delegate - * {@link ThreadPoolFactory} to implement special thread pool strategy. Created by liuruisen on 2019/12/17. - */ -public interface Processor { - - /** - * ServiceRegistry is responsible for holding ServiceInvoker objects. Get ServiceInvoker from ServiceRegistry. - * - * @return ServiceRegistry - */ - ServiceRegistry getRegistry(); - - /** - * Process Rpc Msg Async process - * - * @param msgBase - * @param context RpcChannel context - */ - void process(MsgBase msgBase, RpcChannel context); - - /** - * Close and release resources - */ - void close(); - - /** - * ThreadPoolFactory is used to execute real biz invoke - */ - void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory); - - /** - * Statistics: the approximate wait request count of the rpc service. - * - * @param serviceKey - * @return - */ - Integer waitTaskCount(String serviceKey); - - /** - * Statistics: the approximate executing task count of the rpc service - * - * @param serviceKey - * @return - */ - Integer processingCount(String serviceKey); - - /** - * Statistics: the approximate completed task count of the rpc service - * - * @param serviceKey - * @return - */ - Long completeCount(String serviceKey); - - /** - * Statistics: the approximate wait request count of all rpc services. - * - * @return - */ - Integer allWaitTaskCount(); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ProxyFactory.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ProxyFactory.java deleted file mode 100644 index 5a256f71..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ProxyFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -/** - * Created by liuruisen on 2019/12/18. - */ -public interface ProxyFactory { - - T getProxy(Class serviceClass, Invoker invoker); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcContext.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcContext.java deleted file mode 100644 index 63e9b664..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcContext.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletRequest; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * ThreadLocal based context Created by liuruisen on 2020/9/2. - */ -public class RpcContext { - - public static final String REMOTE_HOST_KEY = "remoteHost"; - public static final String REMOTE_PORT_KEY = "remotePort"; - public static final String PARMS_KEY = "parmeters"; - public static final String PARMTYPES_KEY = "parameterTypes"; - public static final String METHODNAME_KEY = "methodName"; - - private static final ThreadLocal RPC_CONTEXT = ThreadLocal.withInitial(RpcContext::new); - - private Map values = new LinkedHashMap<>(); - - private Integer requestTimeoutMills; - - private String remoteHost; - - private Integer remotePort; - - public static RpcContext getContext() { - return RPC_CONTEXT.get(); - } - - public static void removeContext() { - RPC_CONTEXT.remove(); - } - - /** - * Get ThreadLocal values - * - * @return - */ - public Map get() { - return values; - } - - /** - * Get ThreadLocal value - * - * @param key - * @param - * @return - */ - public T get(String key) { - return (T) values.get(key); - } - - /** - * Add k-v value - * - * @param key - * @param value - * @return - */ - public RpcContext set(String key, Object value) { - values.put(key, value); - return this; - } - - /** - * Will override old values - * - * @param values - * @return - */ - public RpcContext set(Map values) { - this.values.clear(); - if (values != null && values.size() > 0) { - this.values.putAll(values); - } - return this; - } - - public RpcContext remove(String key) { - values.remove(key); - return this; - } - - /** - * Get Session Id - * - * @return - */ - public String getSessionID() { - return get(Constants.SESSION_ID_KEY); - } - - /** - * Set Session ID - * - * @param sessionID - */ - public void setSessionID(String sessionID) { - set(Constants.SESSION_ID_KEY, sessionID); - } - - /** - * Get Request ID - * - * @return - */ - public String getRequestID() { - return get(Constants.REQUEST_ID_KEY); - } - - /** - * Set Request ID - * - * @param requestID - */ - public void setRequestID(String requestID) { - set(Constants.REQUEST_ID_KEY, requestID); - } - - /** - * Set requestTimeout - * - * @param requestTimeoutMills - */ - public void setRequestTimeoutMills(Integer requestTimeoutMills) { - this.requestTimeoutMills = requestTimeoutMills; - } - - public Integer getRequestTimeoutMills() { - return this.requestTimeoutMills; - } - - /** - * set remote address. - * - * @param host - * @param port - * @return context - */ - public RpcContext setRemoteAddress(String host, int port) { - if (port < 0) { - port = 0; - } - setRemoteHost(host); - setRemotePort(port); - return this; - } - - public void setRemoteHost(String remoteHost) { - this.remoteHost = remoteHost; - } - - public void setRemotePort(Integer remotePort) { - this.remotePort = remotePort; - } - - /** - * get remote address string. - * - * @return remote address string. - */ - public String getRemoteAddressString() { - return getRemoteHostName() + ":" + getRemotePort(); - } - - /** - * get remote host name. - * - * @return remote host name - */ - public String getRemoteHostName() { - return remoteHost; - } - - /** - * get remote port. - * - * @return remote port - */ - public int getRemotePort() { - return remotePort == null ? 0 : remotePort; - } - - /** - * get HttpServletRequest if has - * - * @return - */ - public HttpServletRequest getServletRequest() { - return get(Constants.SERVLET_REQUEST_KEY); - } - - /** - * get HttpServletResponse if has - * - * @return - */ - public HttpServletResponse getServletResponse() { - return get(Constants.SERVLET_RESPONSE_KEY); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcService.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcService.java deleted file mode 100644 index f7767c59..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/RpcService.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Abstraction of a rpc service Created by liuruisen on 2019/12/18. - */ -public class RpcService { - private static final Logger LOGGER = LoggerFactory.getLogger(RpcService.class); - /** - * The unique identifier of the service, the value could be <1> service Interface name <2> - * group:interfaceName:version - * - * @return - */ - private String serviceName; - - /** - * The interface class of this service - */ - private Class serviceClass; - - /** - * The object of service class - */ - private Object serviceObj; - - /** - * The config of this service: group version ... - */ - private ServiceConfig serviceConfig; - - /** - * Cache the target methods of this service - */ - private Map methodMap; - - public RpcService(Class serviceClass, Object serviceObj) { - this.serviceClass = serviceClass; - this.serviceObj = serviceObj; - - ServiceConfig config = new ServiceConfig(); - config.setFilters(Constants.DEFAULT_SERVER_FILTERS); - this.serviceConfig = config; - - this.methodMap = new ConcurrentHashMap<>(); - cacheMethod(); - } - - public RpcService(Class serviceClass, Object serviceObj, ServiceConfig serviceConfig) { - this.serviceClass = serviceClass; - this.serviceObj = serviceObj; - this.serviceConfig = serviceConfig; - this.methodMap = new ConcurrentHashMap<>(); - cacheMethod(); - } - - /** - * ServiceKey Default value is service interface name - * - * @return - */ - public String getServiceName() { - if (!StringUtils.isBlank(serviceName)) { - return serviceName; - } - serviceName = serviceConfig.serviceName(serviceClass); - return serviceName; - } - - /** - * ServiceInterface - * - * @return - */ - public Class getServiceClass() { - return serviceClass; - } - - /** - * ServiceObject Implement of service interface - * - * @return - */ - public Object getServiceObject() { - return serviceObj; - } - - /** - * Get invoke method by methodKey - * - * @param methodName - * @return - */ - public Method getMethod(String methodName) { - return methodMap.get(methodName); - } - - /** - * Get RpcService config - * - * @return - */ - public ServiceConfig getServiceConfig() { - return serviceConfig; - } - - /** - * Set RpcService config - * - * @param serviceConfig - */ - public void setServiceConfig(ServiceConfig serviceConfig) { - this.serviceConfig = serviceConfig; - } - - private void cacheMethod() { - Method[] methods = serviceClass.getMethods(); - for (Method method : methods) { - if (isObjectNativeMethod(method)) { - continue; - } - if (methodMap.get(method.getName()) != null) { - throw new IllegalArgumentException( - "Starlight not support method overloading, {" + method.getName() + "}"); - } - methodMap.put(method.getName(), method); - LOGGER.debug("Cache RpcService {}, method {}", getServiceName(), method.getName()); - } - } - - private boolean isObjectNativeMethod(Method method) { - if (method.getDeclaringClass() == Object.class) { - return true; - } - - return false; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("RpcService{"); - sb.append("serviceName='").append(serviceName).append('\''); - sb.append(", serviceClass=").append(serviceClass); - sb.append(", serviceObj=").append(serviceObj); - sb.append(", serviceConfig=").append(serviceConfig); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceInvoker.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceInvoker.java deleted file mode 100644 index 13bdda8d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceInvoker.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -/** - * Service Invoker: Created by liuruisen on 2019/12/18. - */ -public interface ServiceInvoker extends Invoker { - - /** - * Return RpcService to execute invoke - * - * @return - */ - RpcService getRpcService(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceRegistry.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceRegistry.java deleted file mode 100644 index 3abc4557..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/ServiceRegistry.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import java.util.Set; - -/** - * Register rpc ServiceInvoker in local memory. Used only in server side. Single Created by liuruisen on 2019/12/18. - */ -public interface ServiceRegistry { - - /** - * Register ServiceInvoker - * - * @param service - */ - void register(ServiceInvoker service); - - /** - * Unregister ServiceInvoker - * - * @param service - */ - void unRegister(ServiceInvoker service); - - /** - * Discover ServiceInvoker - * - * @param serviceName - * @return - */ - ServiceInvoker discover(String serviceName); - - /** - * Get all rpc ServiceInvoker - * - * @return - */ - Set rpcServices(); - - /** - * Destory and clear resource - */ - void destroy(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightClient.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightClient.java deleted file mode 100644 index cf1c5db4..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightClient.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.PeerStatus; - -/** - * StarlightClient: user interface used to Have both SingleStarlightClient and ClusterStarlightClient types Created by - * liuruisen on 2020/1/3. - */ -public interface StarlightClient { - - /** - * {@link URI} held by StarlightClient - * - * @return - */ - URI remoteURI(); - - /** - * Init StarlightClient: init {@link ClientPeer} by Uri Uri: host:port + config params. in single model, host is ip; - * in cluster model, host is service name - */ - void init(); - - /** - * Generate {@link ClientInvoker} for the service Class - * - * @param serviceClass - * @param serviceConfig - */ - void refer(Class serviceClass, ServiceConfig serviceConfig); - - /** - * Async Request: use {@link ClientInvoker} to call - * - * @param request Request model - * @param callback RpcCallback: BizWrapCallback or FutureCallback - */ - void request(Request request, RpcCallback callback); - - /** - * Clean resources And destroy self - */ - void destroy(); - - /** - * If the starlight client is active Pay attention to the difference between cluster and single client scenarios - * - * @return - */ - boolean isActive(); - - /** - * Get the status of the SingleClient - * - * @return - */ - PeerStatus getStatus(); - - /** - * Can update status - * - * @param newStatus - */ - void updateStatus(PeerStatus newStatus); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightServer.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightServer.java deleted file mode 100644 index a6ca0d2d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/StarlightServer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; - -/** - * Create a rpc server and expose the rpc services Please call {@link StarlightServer#serve()} to start server Created - * by liuruisen on 2019/12/18. - */ -public interface StarlightServer { - - /** - * init the StarlightServer - */ - void init(); - - /** - * Start serve - */ - void serve(); - - /** - * Destroy the server and Clear resources - */ - void destroy(); - - /** - * export rpc service by InterfaceClass and rpcObject - * - * @param rpcInterface - * @param rpcObject - */ - void export(Class rpcInterface, Object rpcObject); - - /** - * export rpc service by InterfaceClass and rpcObject - * - * @param rpcInterface - * @param rpcObject - * @param serviceConfig - */ - void export(Class rpcInterface, Object rpcObject, ServiceConfig serviceConfig); - - /** - * Export By {@link RpcService} - * - * @param rpcService - */ - void export(RpcService rpcService); - - /** - * unExport the service - * - * @param rpcInterface - */ - void unexport(Class rpcInterface); - - /** - * Unexport by {@link RpcService} - * - * @param rpcService - */ - void unexport(RpcService rpcService); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/Callback.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/Callback.java deleted file mode 100644 index d2bb9344..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/Callback.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.callback; - -/** - * Provide callback interface for biz only Created by liuruisen on 2019/12/6. - */ -public interface Callback { - - void onResponse(T response); - - void onError(Throwable e); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/RpcCallback.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/RpcCallback.java deleted file mode 100644 index dc55f747..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/callback/RpcCallback.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.callback; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.util.Timeout; - -/** - * Created by liuruisen on 2020/2/20. - */ -public interface RpcCallback extends Callback { - /** - * Timeout will be set by Invoker - * - * @param timeout - */ - void addTimeout(Timeout timeout); - - /** - * Get Request of the Callback - * - * @return - */ - Request getRequest(); - - default void addRpcChannel(RpcChannel rpcChannel) { - throw new UnsupportedOperationException(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfig.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfig.java deleted file mode 100644 index ca42ef25..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfig.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.config; - -import com.baidu.cloud.starlight.api.utils.StringUtils; - -/** - * Rpc Service config: Interface Use to config rpc service Created by liuruisen on 2020/2/24. - */ -public class ServiceConfig { - - /** - * User-defined service id When using brpc for cross-language communication, the service name will be specified by - * the user. - */ - private String serviceId; - - /** - * Support service dimension protocol, If this field is specified, only that protocol will be used Note: not used - * currently - */ - private String protocol; - - /** - * Support service dimension compressType, if this field is specified, will use this compress type to compress - * request bytes and response bytes. Note: not used currently - */ - private String compressType; - - /** - * Only used in brpc protocol currently - * - * "pb2-std": metadata proto2, body proto2 "pb2-java": meta proto2, body preserve null - */ - private String serializeMode; - - /** - * Support service dimension filters, if this field is specified, will use theses filters to filter request and - * response. Note: not used currently - */ - private String filters; - - /** - * timeout for calling target method - */ - private Integer invokeTimeoutMills; - - /** - * When using stargate communication, you need to specify the group and version information. Default value is - * "normal". Only used in stargate request. - */ - private String group = "normal"; - - /** - * When using stargate communication, you need to specify the group and version information. Default value is - * "1.0.0" Only used in stargate request. - */ - private String version = "1.0.0"; - - /*********** Server Side only: ThreadPool config ***********/ - private Integer threadPoolSize; // biz thread pool size - - private Integer maxThreadPoolSize; - - private Integer maxRunnableQueueSize; - - private Integer idleThreadKeepAliveSecond; - - public String getServiceId() { - return serviceId; - } - - public void setServiceId(String serviceId) { - this.serviceId = serviceId; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getFilters() { - return filters; - } - - public void setFilters(String filters) { - this.filters = filters; - } - - public Integer getInvokeTimeoutMills() { - return invokeTimeoutMills; - } - - public void setInvokeTimeoutMills(Integer invokeTimeoutMills) { - this.invokeTimeoutMills = invokeTimeoutMills; - } - - public Integer getThreadPoolSize() { - return threadPoolSize; - } - - public void setThreadPoolSize(Integer threadPoolSize) { - this.threadPoolSize = threadPoolSize; - } - - public Integer getMaxThreadPoolSize() { - return maxThreadPoolSize; - } - - public void setMaxThreadPoolSize(Integer maxThreadPoolSize) { - this.maxThreadPoolSize = maxThreadPoolSize; - } - - public Integer getMaxRunnableQueueSize() { - return maxRunnableQueueSize; - } - - public void setMaxRunnableQueueSize(Integer maxRunnableQueueSize) { - this.maxRunnableQueueSize = maxRunnableQueueSize; - } - - public Integer getIdleThreadKeepAliveSecond() { - return idleThreadKeepAliveSecond; - } - - public void setIdleThreadKeepAliveSecond(Integer idleThreadKeepAliveSecond) { - this.idleThreadKeepAliveSecond = idleThreadKeepAliveSecond; - } - - public String getCompressType() { - return compressType; - } - - public void setCompressType(String compressType) { - this.compressType = compressType; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getSerializeMode() { - return serializeMode; - } - - public void setSerializeMode(String serializeMode) { - this.serializeMode = serializeMode; - } - - /** - * Get unique ServiceName for target service. The value can be - *
    - *
  • serviceId
  • - *
  • interfaceName
  • - *
- * - * @param serviceClass - * @return - */ - public String serviceName(Class serviceClass) { - // Support cross-language requirements in Brpc scenarios: user can defined serviceName - if (!StringUtils.isBlank(serviceId)) { - return this.getServiceId(); - } - - return serviceClass.getName(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/TransportConfig.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/TransportConfig.java deleted file mode 100644 index ae7e35dd..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/config/TransportConfig.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.config; - -import java.util.Map; - -/** - * Rpc Core configuration Created by liuruisen on 2020/2/24. - */ -public class TransportConfig { - - private Integer connectTimeoutMills; - - private Integer writeTimeoutMills; - - private Integer requestTimeoutMills; - - private Integer readIdleTimeout; // second - - private Integer allIdleTimeout; // second - - private Integer maxHeartbeatTimes; - - private Integer ioThreadNum; - - private Integer acceptThreadNum; - - private String channelType; - - private Integer maxConnections; - - private Integer maxIdleConnections; - - private Integer minIdleConnections; - - private Integer bizWorkThreadNum; - - private Integer ioRatio; - - /********* gracefully shutdown config **********/ - private Boolean gracefullyShutdown; - - private Integer gracefullyQuietPeriod; - - private Integer gracefullyTimeout; - - private Boolean connectKeepAliveEnable; - - // Additional configuration: such as service governance configuration - private Map additional; - - public Integer getConnectTimeoutMills() { - return connectTimeoutMills; - } - - public void setConnectTimeoutMills(Integer connectTimeoutMills) { - this.connectTimeoutMills = connectTimeoutMills; - } - - public Integer getWriteTimeoutMills() { - return writeTimeoutMills; - } - - public void setWriteTimeoutMills(Integer writeTimeoutMills) { - this.writeTimeoutMills = writeTimeoutMills; - } - - public Integer getReadIdleTimeout() { - return readIdleTimeout; - } - - public void setReadIdleTimeout(Integer readIdleTimeout) { - this.readIdleTimeout = readIdleTimeout; - } - - public Integer getAllIdleTimeout() { - return allIdleTimeout; - } - - public void setAllIdleTimeout(Integer allIdleTimeout) { - this.allIdleTimeout = allIdleTimeout; - } - - public Integer getMaxHeartbeatTimes() { - return maxHeartbeatTimes; - } - - public void setMaxHeartbeatTimes(Integer maxHeartbeatTimes) { - this.maxHeartbeatTimes = maxHeartbeatTimes; - } - - public Integer getIoThreadNum() { - return ioThreadNum; - } - - public void setIoThreadNum(Integer ioThreadNum) { - this.ioThreadNum = ioThreadNum; - } - - public Integer getAcceptThreadNum() { - return acceptThreadNum; - } - - public void setAcceptThreadNum(Integer acceptThreadNum) { - this.acceptThreadNum = acceptThreadNum; - } - - public String getChannelType() { - return channelType; - } - - public void setChannelType(String channelType) { - this.channelType = channelType; - } - - public Integer getMaxConnections() { - return maxConnections; - } - - public void setMaxConnections(Integer maxConnections) { - this.maxConnections = maxConnections; - } - - public Integer getMaxIdleConnections() { - return maxIdleConnections; - } - - public void setMaxIdleConnections(Integer maxIdleConnections) { - this.maxIdleConnections = maxIdleConnections; - } - - public Integer getMinIdleConnections() { - return minIdleConnections; - } - - public void setMinIdleConnections(Integer minIdleConnections) { - this.minIdleConnections = minIdleConnections; - } - - public Integer getRequestTimeoutMills() { - return requestTimeoutMills; - } - - public void setRequestTimeoutMills(Integer requestTimeoutMills) { - this.requestTimeoutMills = requestTimeoutMills; - } - - public Boolean getGracefullyShutdown() { - return gracefullyShutdown; - } - - public void setGracefullyShutdown(Boolean gracefullyShutdown) { - this.gracefullyShutdown = gracefullyShutdown; - } - - public Integer getGracefullyQuietPeriod() { - return gracefullyQuietPeriod; - } - - public void setGracefullyQuietPeriod(Integer gracefullyQuietPeriod) { - this.gracefullyQuietPeriod = gracefullyQuietPeriod; - } - - public Integer getGracefullyTimeout() { - return gracefullyTimeout; - } - - public void setGracefullyTimeout(Integer gracefullyTimeout) { - this.gracefullyTimeout = gracefullyTimeout; - } - - public Boolean getConnectKeepAliveEnable() { - return connectKeepAliveEnable; - } - - public void setConnectKeepAliveEnable(Boolean connectKeepAliveEnable) { - this.connectKeepAliveEnable = connectKeepAliveEnable; - } - - public Map getAdditional() { - return additional; - } - - public void setAdditional(Map additional) { - this.additional = additional; - } - - public Integer getBizWorkThreadNum() { - return bizWorkThreadNum; - } - - public void setBizWorkThreadNum(Integer bizWorkThreadNum) { - this.bizWorkThreadNum = bizWorkThreadNum; - } - - public Integer getIoRatio() { - return ioRatio; - } - - public void setIoRatio(Integer ioRatio) { - this.ioRatio = ioRatio; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/proxy/ProxyFactory.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/proxy/ProxyFactory.java deleted file mode 100644 index c6211d3e..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/proxy/ProxyFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; - -/** - * Created by liuruisen on 2020/1/4. - */ -public interface ProxyFactory { - - /** - * Generate proxy - * - * @param targetType proxyType - * @param serviceConfig target service config: serviceId protocol - * @param client StarlightClient will be used to call remote - * @param - * @return - */ - T getProxy(Class targetType, ServiceConfig serviceConfig, StarlightClient client); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/RpcSseEmitter.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/RpcSseEmitter.java deleted file mode 100644 index 7bfee088..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/RpcSseEmitter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.sse; - -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -import java.io.IOException; -import java.util.function.Consumer; - -public interface RpcSseEmitter { - - void init(RpcCallback rpcCallback); - - void send(T data) throws IOException; - - void send(SseEventBuilder builder) throws IOException; - - void complete(); - - void completeWithError(Throwable ex); - - void onTimeout(Runnable callback); - - void onError(Consumer callback); - - void onCompletion(Runnable callback); - - void onServerEvent(Consumer callback); - - void onData(Consumer callback); - - void close(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/ServerEvent.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/ServerEvent.java deleted file mode 100644 index fb823451..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/ServerEvent.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.sse; - -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; - -public class ServerEvent { - - public static final ServerEvent START_EVENT = new ServerEvent(); - - public static final ServerEvent COMPLETE_EVENT = new ServerEvent(); - - private String data; - private String id; - private String event; - private long retry; - private String comment; - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getEvent() { - return event; - } - - public void setEvent(String event) { - this.event = event; - } - - public long getRetry() { - return retry; - } - - public void setRetry(long retry) { - this.retry = retry; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public String toData() { - StringBuffer sb = new StringBuffer(); - if (!StringUtils.isBlank(id)) { - sb.append("id:").append(id).append('\n'); - } - if (!StringUtils.isBlank(event)) { - sb.append("event:").append(event).append('\n'); - } - if (retry > 0) { - sb.append("retry:").append(retry).append('\n'); - } - if (!StringUtils.isBlank(comment)) { - sb.append(":").append(comment).append('\n'); - } - if (!StringUtils.isBlank(data)) { - StringUtils.replace(data, "\n", "\ndata:"); - sb.append("data:").append(data).append("\n"); - } - sb.append("\n"); - - return sb.toString(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/SseEventBuilder.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/SseEventBuilder.java deleted file mode 100644 index 7a698858..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/sse/SseEventBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.sse; - -public interface SseEventBuilder { - SseEventBuilder id(String id); - - SseEventBuilder event(String eventName); - - SseEventBuilder retry(long retryMillis); - - SseEventBuilder comment(String comment); - - SseEventBuilder data(T data); - - ServerEvent build() throws Exception; -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/NamedThreadFactory.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/NamedThreadFactory.java deleted file mode 100644 index b97f53d3..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/NamedThreadFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.threadpool; - -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class NamedThreadFactory implements ThreadFactory { - - private AtomicInteger threadNumber = new AtomicInteger(1); - private String namePrefix; - - public NamedThreadFactory(String namePrefix) { - this.namePrefix = namePrefix + "-"; - } - - @Override - public Thread newThread(Runnable r) { - Thread thread = Executors.defaultThreadFactory().newThread(r); - String name = namePrefix + threadNumber.getAndIncrement(); - thread.setName(name); - thread.setDaemon(true); - thread.setPriority(Thread.NORM_PRIORITY); - return thread; - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/ThreadPoolFactory.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/ThreadPoolFactory.java deleted file mode 100644 index b2cf2ab8..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/rpc/threadpool/ThreadPoolFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.threadpool; - -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.RpcService; - -import java.util.concurrent.ThreadPoolExecutor; - -/** - * Thread pool factory for getting or creating Threadpool. Used by {@link Processor} Created by liuruisen on 2019/12/17. - */ -public interface ThreadPoolFactory { - - /** - * Get or create ThreadPool for serviceKey If no thread pool is specified, the default thread pool is returned - * - * @param rpcService - * @return - */ - ThreadPoolExecutor getThreadPool(RpcService rpcService); - - /** - * Get default Thread pool - * - * @return - */ - ThreadPoolExecutor getThreadPool(); - - /** - * Close the thread pool factory Resource clear,clear the task and close the thread pool - */ - void close(); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/compressor/Compress.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/compressor/Compress.java deleted file mode 100644 index 4b73f47e..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/compressor/Compress.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.serialization.compressor; - -import com.baidu.cloud.starlight.api.exception.CodecException; - -/** - * SPI Compressor Created by liuruisen on 2020/2/7. - */ -public interface Compress { - - /** - * compress byte[] - * - * @param inputByte - * @return - * @throws CodecException - */ - byte[] compress(byte[] inputByte) throws CodecException; - - /** - * uncompress byte[] - * - * @param inputByte - * @return - * @throws CodecException - */ - byte[] decompress(byte[] inputByte) throws CodecException; -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/serializer/Serializer.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/serializer/Serializer.java deleted file mode 100644 index 8c3800ce..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/serialization/serializer/Serializer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Type; - -/** - * Serialize param obj to bytes, or deserialize bytes to param obj. Only serialize or deserialize, Encode see - * {@link ProtocolEncoder} Decode see {@link ProtocolDecoder} Supported SPI Created by liuruisen on 2019/12/4. - */ -public interface Serializer { - - Logger LOGGER = LoggerFactory.getLogger(Serializer.class); - - String DESERIALIZE_ERROR_MSG = - "The problem is usually caused by" + "\n 1: difference of api.jar between server and client." - + "\n 2: API contains a type that Starlight(stargate) does not support. eg:HashMap.keySet()"; - - byte[] serialize(Object obj, Type type) throws CodecException; - - Object deserialize(byte[] bytes, Type type) throws CodecException; -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/CountStats.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/CountStats.java deleted file mode 100644 index 8df783b8..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/CountStats.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.statistics; - -/** - * 请求Count统计信息 Created by liuruisen on 2021/9/18. - */ -public interface CountStats extends Stats { - - /** - * Total request count - * - * @return - */ - Integer totalReqCount(); - - /** - * Failed request count - * - * @return - */ - Integer failReqCount(); - - /** - * Success request count - * - * @return - */ - Integer sucReqCount(); - - /** - * Record - * - * @param success - */ - void recordReqCount(boolean success); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/Stats.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/Stats.java deleted file mode 100644 index badca5a3..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/statistics/Stats.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.statistics; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; - -/** - * Capture various statistics per client(instance) Created by liuruisen on 2021/4/18. - */ -public interface Stats { - - /** - * Record stats - * - * @param request - * @param response - */ - void record(Request request, Response response); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ClientPeer.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ClientPeer.java deleted file mode 100644 index a57c3a4d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ClientPeer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannelGroup; - -/** - * Client Peer: Netty Client Use {@link RpcChannel} to communicate with ServerPeer Created by liuruisen on 2019/11/27. - */ -public interface ClientPeer extends Peer { - - /** - * get Channel - * - * @return RpcChannel: Client Channel manager: Short Long Pool - */ - RpcChannelGroup getChannelGroup(); - - /** - * Use {@link RpcChannel} to Connect to ServerPeer - */ - void connect(); - - /** - * Use {@link RpcChannel} to send message Callbacks will be stored in RpcChannel - * - * @param request - * @param callback async {@link RpcCallback} - */ - void request(Request request, RpcCallback callback) throws TransportException; - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/GracefullyShutdown.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/GracefullyShutdown.java deleted file mode 100644 index acf80ef0..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/GracefullyShutdown.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.model.ShuttingDownEvent; - -/** - * Created by liuruisen on 2020/11/27. - */ -public interface GracefullyShutdown { - - /** - * In the process of graceful shutdown, a very small amount of traffic is allowed to enter during the quiet period. - * After the quiet period, no traffic is allowed to enter. When the timeout period is reached or the task is - * completed, exit - * - * @param quietPeriod - * @param timeout - */ - void gracefullyShutdown(long quietPeriod, long timeout); - - /** - * SHUTTING_DOWN_EVENT - * - * @param protocol - * @return - */ - default RpcResponse shuttingDownEvent(String protocol) { - RpcResponse shutdownEvent = new RpcResponse(0); - shutdownEvent.setResult(new ShuttingDownEvent(System.currentTimeMillis())); - shutdownEvent.setStatus(Constants.SUCCESS_CODE); - shutdownEvent.setProtocolName(protocol); - shutdownEvent.setReturnType(ShuttingDownEvent.class); - - return shutdownEvent; - } - - /** - * When is shutting down, response this - * - * @param request - * @return - */ - default RpcResponse shuttingDownResponse(Request request) { - RpcResponse response = new RpcResponse(request.getId()); - response.setRequest(request); - response.setProtocolName(request.getProtocolName()); - response.setStatus(TransportException.SHUTTING_DOWN); - response.setErrorMsg("The request will not be execute because it is shutting down"); - return response; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/Peer.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/Peer.java deleted file mode 100644 index 2d73f958..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/Peer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.thirdparty.netty.util.internal.NativeLibraryLoader; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * Network peer Created by liuruisen on 2019/11/27. - */ -public interface Peer extends GracefullyShutdown { - - void init(); - - /** - * get Uri: IP+Port and Config - */ - URI getUri(); - - /** - * close and clear resources - * - * @see ClientPeer - * @see ServerPeer - */ - void close(); - - /** - * Execute biz work by Processor Processor to handle request {@link Processor} - */ - void setProcessor(Processor processor); - - /** - * Get processor - * - * @return - */ - Processor getProcessor(); - - /** - * Get status of the peer include the status record time - * - * @return - */ - PeerStatus status(); - - /** - * Update the status of peer and record the statusChangeTime - * - * @param status - */ - void updateStatus(PeerStatus status); - - /** - * starlight中使用的netty so文件与业务应用中使用的要区分开,防止业务也使用netty报错不兼容 issue:https://github.com/baidu/starlight/issues/360 - */ - default void updateNettyResourceMetaHome() { - try { - Class loaderClass = NativeLibraryLoader.class; - Field homeFiled = loaderClass.getDeclaredField("NATIVE_RESOURCE_HOME"); - homeFiled.setAccessible(true); - // 去除final修饰符的影响,将字段设为可修改的 - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(homeFiled, homeFiled.getModifiers() & ~Modifier.FINAL); - // 修改字段的内容 - homeFiled.set(null, "META-INF/native/thirdparty"); - } catch (Throwable e) { - // ignore - } - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/PeerStatus.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/PeerStatus.java deleted file mode 100644 index 10a4563e..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/PeerStatus.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import java.util.Objects; - -/** - * Created by liuruisen on 2020/11/27. - */ -public class PeerStatus { - - private Status status; - - /** - * Record the status time, the value of time is System.currentTimeMillis() - */ - private Long statusRecordTime; - - /** - * Record the reason for changing to this status - */ - private Object statusReason; - - public PeerStatus(Status status, Long statusRecordTime) { - this.status = status; - this.statusRecordTime = statusRecordTime; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public Long getStatusRecordTime() { - return statusRecordTime; - } - - public void setStatusRecordTime(Long statusRecordTime) { - this.statusRecordTime = statusRecordTime; - } - - public Object getStatusReason() { - return statusReason; - } - - public void setStatusReason(Object statusReason) { - this.statusReason = statusReason; - } - - /** - * Status of the client or server. ACTIVE exchange to OUTLIER ACTIVE to SHUTTING DOWN to SHUTDOWN - */ - public enum Status { - /** - * The peer is active - */ - ACTIVE, - - /** - * The peer is outlier - */ - OUTLIER, - - /** - * The peer is shutting down - */ - SHUTTING_DOWN, - - /** - * The peer is shutdown - */ - SHUTDOWN - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("PeerStatus{"); - sb.append("status=").append(status); - sb.append(", statusRecordTime=").append(statusRecordTime); - sb.append('}'); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - PeerStatus that = (PeerStatus) o; - return status == that.status && Objects.equals(statusRecordTime, that.statusRecordTime); - } - - @Override - public int hashCode() { - return Objects.hash(status, statusRecordTime); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ServerPeer.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ServerPeer.java deleted file mode 100644 index c35f6e5f..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/ServerPeer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; - -import java.util.Map; - -/** - * ServerPeer: Netty Server Bind to ip + port, accept connection and request. Use NettyInboundHandler to handle request. - * Created by liuruisen on 2019/11/27. - */ -public interface ServerPeer extends Peer { - - /** - * Bind to settled Url(IP + Port) - */ - void bind(); - - /** - * Is bound - * - * @return - */ - boolean isBound(); - - /** - * RpcChannels connected to the server The method must be thread-safe - * - * @return - */ - Map rpcChannels(); - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/TransportFactory.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/TransportFactory.java deleted file mode 100644 index 3eb61eae..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/TransportFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport; - -import com.baidu.cloud.starlight.api.common.URI; - -/** - * SPI Factory of Transport Created by liuruisen on 2020/1/16. - */ -public interface TransportFactory { - - /** - * Get or Create ClientPeer by URI - * - * @param uri ip + port + net config - * @return - */ - ClientPeer client(URI uri); - - /** - * Get or Create ServerPeer by URI - * - * @param uri ip + port + net config - * @return - */ - ServerPeer server(URI uri); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelAttribute.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelAttribute.java deleted file mode 100644 index 732ba0a7..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelAttribute.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport.channel; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; - -/** - * Created by liuruisen on 2020/3/31. - */ -public class ChannelAttribute { - - // Channel dimension ByteBuf - private DynamicCompositeByteBuf dynamicByteBuf; - - private final RpcChannel rpcChannel; - - public ChannelAttribute(RpcChannel rpcChannel) { - this.rpcChannel = rpcChannel; - this.dynamicByteBuf = new DynamicCompositeByteBuf(16); - } - - public DynamicCompositeByteBuf getDynamicByteBuf() { - return dynamicByteBuf; - } - - public RpcChannel getRpcChannel() { - return rpcChannel; - } - - public String getChannelProtocol() { - return (String) rpcChannel.getAttribute(Constants.PROTOCOL_ATTR_KEY); - } - - public void resetChannelProtocol(String protocolName) { - rpcChannel.setAttribute(Constants.PROTOCOL_ATTR_KEY, protocolName); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelSide.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelSide.java deleted file mode 100644 index edaa2cf1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ChannelSide.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport.channel; - -/** - * Created by liuruisen on 2020/11/25. - */ -public enum ChannelSide { - - /** - * Server side Channel - */ - SERVER, - - /** - * Client side channel - */ - CLIENT - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannel.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannel.java deleted file mode 100644 index 59bcd330..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannel.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport.channel; - -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.util.AttributeKey; - -import java.net.InetSocketAddress; -import java.util.Map; - -/** - * RpcChannel. Used to Connect Channel, Write Message, Read Message Created by liuruisen on 2019/11/27. - */ -public interface RpcChannel { - - /** - * Channel attribute - **/ - AttributeKey ATTRIBUTE_KEY = AttributeKey.valueOf("channel.attribute"); - - /** - * RpcChannel Side - * - * @return - */ - ChannelSide side(); - - /** - * Return the remote address when the channel is connected to. - * - * @return - */ - InetSocketAddress getRemoteAddress(); - - /** - * Return the local address when the channel is bound to. fixme 是否需要 - * - * @return - */ - InetSocketAddress getLocalAddress(); - - /** - * RpcChannel is active - * - * @return - */ - boolean isActive(); - - /** - * Get real network communication Netty {@link Channel} The channel must active ? - * - * @return - */ - Channel channel(); - - /** - * reconnect the channel - * - */ - void reconnect() throws TransportException; - - /** - * Init RpcChannel - */ - void init(); - - /** - * Close Channel and clear resources Gracefully shutdown NOTICE: This stage may be time-consuming - */ - void close(); - - /** - * Send message. Select a real Netty Channel to writeAndFlush message Or change to getChannel() - * - * @param msgBase - * @throws TransportException - */ - void send(MsgBase msgBase) throws TransportException; - - /** - * Receive message. Do something when receive message, such as: statistic - * - * @param msgBase - */ - void receive(MsgBase msgBase); - - /** - * Register Callback to Channel, this callback is handle through the channel - * - * @param id - * @param callback - */ - void putCallback(long id, RpcCallback callback); - - /** - * Remove RpcCallback by id - * - * @param id - * @return - */ - RpcCallback removeCallback(long id); - - /** - * Get all callbacks processed by this instance - * - * @return - */ - Map allCallbacks(); - - /** - * Allow to store a value reference. It is thread-safe - * - * @param attributeKey - * @param attributeVal - */ - void setAttribute(String attributeKey, Object attributeVal); - - /** - * Return the attribute releated to the key - * - * @param attributeKey - * @return - */ - Object getAttribute(String attributeKey); - - /** - * Remove the attribute releated to the key - * - * Returns: the previous value associated with key, or null if there was no mapping for key. - */ - Object removeAttribute(String attributeKey); - - /** - * Get RpcChannel linked RpcChannelGroup - * - * @return - */ - RpcChannelGroup getRpcChannelGroup(); - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannelGroup.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannelGroup.java deleted file mode 100644 index cf19e34d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/RpcChannelGroup.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport.channel; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; - -import java.util.Set; - -/** - * - * Created by liuruisen on 2020/11/25. - */ -public interface RpcChannelGroup { - - /** - * Init and prepare RpcChannels - */ - void init(); - - /** - * Get Channel Uri - * - * @return - */ - URI getUri(); - - /** - * Randomly get or create one RpcChannel from the group The RpcChannel returned must be active. - * - * NOTICE: This method may connect to remote and may throw transport exception - * - * @return - */ - RpcChannel getRpcChannel() throws TransportException; - - /** - * Return the RpcChannel to group, so it can be reuse - * - * @param rpcChannel - */ - void returnRpcChannel(RpcChannel rpcChannel); - - /** - * Remove the RpcChannel from group. Will create a new RpcChannel and add to the group - * - * @param rpcChannel - */ - void removeRpcChannel(RpcChannel rpcChannel); - - /** - * How many RpcChannel in the group - * - * @return - */ - int rpcChannelCount(); - - /** - * Close all RpcChannel in the RpcChannelGroup - */ - void close(); - - /** - * Get All RpcChannels in the group - * - * @return - */ - Set allRpcChannels(); -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ThreadLocalChannelContext.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ThreadLocalChannelContext.java deleted file mode 100644 index 75d57c2b..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/transport/channel/ThreadLocalChannelContext.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.transport.channel; - -import com.baidu.cloud.thirdparty.netty.channel.Channel; - -/** - * ThreadLocal Netty Channel Context Store thread-local netty {@link Channel} information, including netty channel and - * {@link ChannelAttribute} - *

- * Created by liuruisen on 2020/11/9. - */ -public class ThreadLocalChannelContext { - - private static final ThreadLocal CHANNEL_CONTEXT = - ThreadLocal.withInitial(ThreadLocalChannelContext::new); - - public static ThreadLocalChannelContext getContext() { - return CHANNEL_CONTEXT.get(); - } - - public static void removeContext() { - CHANNEL_CONTEXT.remove(); - } - - private Channel channel; - - public Channel getChannel() { - return channel; - } - - public void setChannel(Channel channel) { - this.channel = channel; - } - - public ChannelAttribute getChannelAttribute() { - if (channel == null) { - return null; - } - return channel.attr(RpcChannel.ATTRIBUTE_KEY).get(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtils.java deleted file mode 100644 index a0fe45f1..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -/** - * Created by liuruisen on 2020/2/20. - */ -public class ByteArrayUtils { - - /** - * 合并byte[]数组 (不改变原数组) - * - * @param bytes1 - * @param bytes2 - * @return 合并后的数组 - */ - public static byte[] byteMerger(byte[] bytes1, byte[] bytes2) { - if (bytes1 == null || bytes1.length == 0) { - return bytes2; - } - if (bytes2 == null || bytes2.length == 0) { - return bytes1; - } - byte[] bytes3 = new byte[bytes1.length + bytes2.length]; - System.arraycopy(bytes1, 0, bytes3, 0, bytes1.length); - System.arraycopy(bytes2, 0, bytes3, bytes1.length, bytes2.length); - return bytes3; - } - - /** - * 截取byte数组 不改变原数组 - * - * @param b 原数组 - * @param off 偏差值(索引) - * @param length 长度 - * @return 截取后的数组 - */ - public static byte[] subByte(byte[] b, int off, int length) { - if (b == null || b.length == 0) { - return b; - } - byte[] b1 = new byte[length]; - System.arraycopy(b, off, b1, 0, length); - return b1; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/CollectionUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/CollectionUtils.java deleted file mode 100644 index 5dc21449..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/CollectionUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import java.util.HashMap; -import java.util.Map; - -/** - * CollectionUtils - */ -public class CollectionUtils { - private CollectionUtils() {} - - public static Map toStringMap(String... pairs) { - Map parameters = new HashMap(); - if (pairs.length > 0) { - if (pairs.length % 2 != 0) { - throw new IllegalArgumentException("pairs must be even."); - } - for (int i = 0; i < pairs.length; i = i + 2) { - parameters.put(pairs[i], pairs[i + 1]); - } - } - return parameters; - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/EnvUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/EnvUtils.java deleted file mode 100644 index e4f2c68d..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/EnvUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; - -/** - * System Environment Utils Created by liuruisen on 2020/11/17. - */ -public class EnvUtils { - - public static int getCpuCores() { - int cpuCores = Runtime.getRuntime().availableProcessors(); - if (isJarvisEnv() && StringUtils.isNumeric(System.getenv(Constants.EM_CPU_CORES))) { - cpuCores = Integer.parseInt(System.getenv(Constants.EM_CPU_CORES)) / 10 * 4; // #单位约0.1核, 超发4 - } - cpuCores = Math.max(8, cpuCores); // min core num = 8 - return cpuCores; - } - - public static int getContainerThreadNum(int defaultValue) { - if (isJarvisEnv() && hasThreadEnvVar()) { - String threadNumber = System.getenv(Constants.EM_THREAD_NUMBER); - return Integer.parseInt(threadNumber.trim()) * 10 / 6; - } else { - return defaultValue; - } - } - - public static boolean isJarvisEnv() { - String emProductLine = System.getenv(Constants.EM_PRODUCT_LINE); - String emPlatform = System.getenv(Constants.EM_PLATFORM); - String emApp = System.getenv(Constants.EM_APP); - - return !StringUtils.isEmpty(emProductLine) && !StringUtils.isEmpty(emPlatform) && !StringUtils.isEmpty(emApp); - } - - public static boolean hasThreadEnvVar() { - String threadNum = System.getenv(Constants.EM_THREAD_NUMBER); - return !StringUtils.isEmpty(threadNum); - } - - public static boolean isJarvisOnline() { - if (!isJarvisEnv()) { - return false; - } - String emEnvType = System.getenv(Constants.EM_ENV_TYPE); - return "ONLINE".equalsIgnoreCase(emEnvType); - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/GenericUtil.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/GenericUtil.java deleted file mode 100644 index fe2dbb5b..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/GenericUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import java.util.HashMap; - -/** - * Created by liuruisen on 2020/4/8. - */ -public class GenericUtil { - - public static boolean isGenericCall(Request request) { - if (request.getMethodName() != null && request.getMethodName().contains(Constants.GENERIC_METHOD_NAME_PREFIX)) { - return true; - } - return false; - } - - public static void markGeneric(MsgBase msgBase) { - if (msgBase.getAttachmentKv() == null) { - msgBase.setAttachmentKv(new HashMap<>()); - } - msgBase.getAttachmentKv().put(Constants.IS_GENERIC_KEY, Boolean.TRUE); - } - - public static boolean isGenericMsg(MsgBase msgBase) { - if (msgBase.getAttachmentKv() != null && msgBase.getAttachmentKv().get(Constants.IS_GENERIC_KEY) != null - && (Boolean) msgBase.getAttachmentKv().get(Constants.IS_GENERIC_KEY)) { - return true; - } - - return false; - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IDGenerator.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IDGenerator.java deleted file mode 100644 index 05e11b3c..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IDGenerator.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Random; - -/** - * 依据snowflake改造的算法,单节点使用,最大限度保持唯一 - */ -public class IDGenerator { - - private static final Logger LOGGER = LoggerFactory.getLogger(IDGenerator.class); - - /** - * 起始的时间戳 2021-07-30 17:33:46 - */ - private static final long START_STMP = 1627637626000L; - - /** - * 每一部分占用的位数 SEQUENCE_BIT: 序列号占用的位数 MACHINE_BIT: 机器标识占用的位数 DATACENTER_BIT: 机房占用的位数 - */ - private static final long SEQUENCE_BIT = 10; - private static final long MACHINE_BIT = 16; - private static final long DATACENTER_BIT = 2; - - /** - * 每一部分的最大值 - */ - private static final long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); - private static final long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); - private static final long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); - - /** - * 每一部分向左的位移 - */ - private static final long MACHINE_LEFT = SEQUENCE_BIT; - private static final long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; - private static final long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; - - private long dataCenterId; // 数据中心 - private long machineId; // 机器标识 - private long sequence = 0L; // 序列号 - private long lastStamp = -1L; // 上一次时间戳 - - private static IDGenerator idGenerator; - - public static IDGenerator getInstance() { - if (idGenerator == null) { - synchronized (IDGenerator.class) { - if (idGenerator == null) { - Random rd = new Random(); - long workerId = rd.nextInt(1 << 16); - long dataCenterId = rd.nextInt(3); // 机房随机数 - - // 获取当前ip,生成工作id - try { - String ip = NetUriUtils.getLocalHost(); - if (ip != null) { - workerId = Long.parseLong(ip.replaceAll("\\.", "")); - workerId = workerId & 0XFFFF; // 取低16位 - } - } catch (Throwable e) { - LOGGER.warn("Generate workerId from ip failed, caused by ", e); - } - idGenerator = new IDGenerator(dataCenterId, workerId); - } - } - } - return idGenerator; - } - - private IDGenerator(long datacenterId, long machineId) { - if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { - throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); - } - if (machineId > MAX_MACHINE_NUM || machineId < 0) { - throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); - } - this.dataCenterId = datacenterId; - this.machineId = machineId; - } - - /** - * 产生下一个ID - * - * @return - */ - public synchronized long nextId() { - long currStmp = getNewstamp(); - if (currStmp < lastStamp) { - throw new RuntimeException("Clock moved backwards. Refusing to generate id"); - } - - if (currStmp == lastStamp) { - // 相同毫秒内,序列号自增 - sequence = (sequence + 1) & MAX_SEQUENCE; - // 同一毫秒的序列数已经达到最大, 等待下一毫秒 - if (sequence == 0L) { - currStmp = getNextMill(); - } - } else { - // 不同毫秒内,序列号置为0 - sequence = 0L; - } - - lastStamp = currStmp; - - return (currStmp - START_STMP) << TIMESTMP_LEFT // 时间戳部分 - | dataCenterId << DATACENTER_LEFT // 机房随机数部分 - | machineId << MACHINE_LEFT // 机器IP标识部分 - | sequence; // 序列号部分 - } - - private long getNextMill() { - long mill = getNewstamp(); - while (mill <= lastStamp) { - mill = getNewstamp(); - } - return mill; - } - - private long getNewstamp() { - return System.currentTimeMillis(); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IdUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IdUtils.java deleted file mode 100644 index 9f551586..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/IdUtils.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.thirdparty.uuid.UUIDGenerator; - -/** - * Created by liuruisen on 2020/9/3. - */ -public class IdUtils { - - public static final String genUUID() { - return UUIDGenerator.getInstance().generateTimeBasedUUID().toString(); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/LogUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/LogUtils.java deleted file mode 100644 index 4e1b9b42..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/LogUtils.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Created by liuruisen on 2021/1/7. - */ -public class LogUtils { - - private static final Logger LOGGER = LoggerFactory.getLogger(LogUtils.class); - - // 凤睛插件的spanContext key - protected static final String PROBE_SPAN_CONTEXT_KEY = "traceSpanContext"; - - protected static final String X_B3_TRACE_ID = "X-B3-TraceId"; - - protected static final String X_B3_SPAN_ID = "X-B3-SpanId"; - - private static final String EQUAL_CHARACTER = "="; - - private static final String AND_CHARACTER = "&"; - - public static final String TCID = "tcid"; - - public static final String SPID = "spid"; - - public static void addLogTimeAttachment(MsgBase msg, String timeKey, long timestamp) { - if (msg.getNoneAdditionKv() == null) { - msg.setNoneAdditionKv(new HashMap<>()); - } - - msg.getNoneAdditionKv().put(timeKey, timestamp); - } - - public static void recordAccessLog(Request request, Response response) { - String accessLogFormat = "[ACCLOG] recvTime {}, respTime {}, remoteName {}, remoteAddr {}, " + "protocol {}, " - + "status {}, cost {}, " + "req {}:{}, " + "decReqHead {}, " + "waitForExec {}, " + "decodeReqBody {}, " - + "execServFilter {}, " + "execMethod {}, " + "encRespBody {}, " + "waitForIoExec {}, " + "encRespHead {}, " - + "tid {}, spid {}"; - - try { - Map traceSpanIdMap = parseTraceIdSpanId(request); - - Long decodeRequestHeaderCost = request.getNoneAdditionKv().get(Constants.DECODE_HEADER_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.DECODE_HEADER_COST)); - - Long decodeRequestBodyCost = request.getNoneAdditionKv().get(Constants.DECODE_BODY_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.DECODE_BODY_COST)); - - Long waitForExecTime = request.getNoneAdditionKv().get(Constants.WAIT_FOR_THREAD_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.WAIT_FOR_THREAD_COST)); - - Long executeMethodCost = request.getNoneAdditionKv().get(Constants.EXECUTE_METHOD_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.EXECUTE_METHOD_COST)); - - Long encodeResponseBodyCost = response.getNoneAdditionKv().get(Constants.ENCODE_BODY_COST) == null ? null - : ((Long) response.getNoneAdditionKv().get(Constants.ENCODE_BODY_COST)); - - Long encodeResponseHeaderCost = response.getNoneAdditionKv().get(Constants.ENCODE_HEADER_COST) == null - ? null : ((Long) response.getNoneAdditionKv().get(Constants.ENCODE_HEADER_COST)); - - Long recvReqTime = request.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY)); - - Long retRespTime = response.getNoneAdditionKv().get(Constants.RETURN_RESPONSE_TIME_KEY) == null ? null - : ((Long) response.getNoneAdditionKv().get(Constants.RETURN_RESPONSE_TIME_KEY)); - - Long serverExecCost = null; - if (recvReqTime != null && retRespTime != null) { - serverExecCost = retRespTime - recvReqTime; - } - - LOGGER.info(accessLogFormat, recvReqTime == null ? null : timestampToString(recvReqTime), // recvReqTime - retRespTime == null ? null : timestampToString(retRespTime), // retRespTime - request.getAttachmentKv().remove(Constants.CONSUMER_APP_NAME_KEY), // consumer name - request.getNoneAdditionKv().get(Constants.REMOTE_ADDRESS_KEY), // consumer addr - request.getProtocolName(), // protocol - response.getStatus(), // status - serverExecCost, // server exec all cost - simpleServiceName(request.getServiceName()), // req service name - request.getMethodName(), // req method name - decodeRequestHeaderCost, // decode req header cost - waitForExecTime, // wait for exec - decodeRequestBodyCost, // decode req body - request.getNoneAdditionKv().get(Constants.SERVER_FILTER_EXEC_COST_KEY), // server filter exec cost - executeMethodCost, // exec method cost - encodeResponseBodyCost, // encode response cost - response.getNoneAdditionKv().get(Constants.WAIT_FOR_IO_THREAD_COST_KEY), // wait for io exec cost - encodeResponseHeaderCost, // encode resp header cost - traceSpanIdMap.get(TCID), traceSpanIdMap.get(SPID)); - - LOGGER.debug("[ACCLOG] Request logKv {}, Response logKv {}", request.getNoneAdditionKv(), - response.getNoneAdditionKv()); - } catch (Exception e) { - LOGGER.warn("Record server access log error, cause by {}", e.getMessage()); - } - } - - public static void recordRequestLog(Request request, Response response) { - - String requestLogFormat = "[REQLOG] reqTime {}, recvTime {}, remoteName {}, remoteAddr {}, " + "protocol {}, " - + "status {}, cost {}, " + "req {}:{}, " + "encReqBody {}, " + "waitForIoExec {}, " + "encReqHead {}, " - + "serverExec {}, " + "decRespHead {}, " + "waitForExec {}, " + "decRespBody {}, " + "tid {}, spid {}"; - try { - Map traceSpanIdMap = parseTraceIdSpanId(request); - - Long encodeRequestBodyCost = request.getNoneAdditionKv().get(Constants.ENCODE_BODY_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.ENCODE_BODY_COST)); - Long encodeRequestHeaderCost = request.getNoneAdditionKv().get(Constants.ENCODE_HEADER_COST) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.ENCODE_HEADER_COST)); - Long waitForThreadCost = response.getNoneAdditionKv().get(Constants.WAIT_FOR_THREAD_COST) == null ? null - : ((Long) response.getNoneAdditionKv().get(Constants.WAIT_FOR_THREAD_COST)); - Long decodeResponseHeaderCost = response.getNoneAdditionKv().get(Constants.DECODE_HEADER_COST) == null - ? null : ((Long) response.getNoneAdditionKv().get(Constants.DECODE_HEADER_COST)); - Long decodeResponseBodyCost = response.getNoneAdditionKv().get(Constants.DECODE_BODY_COST) == null ? null - : ((Long) response.getNoneAdditionKv().get(Constants.DECODE_BODY_COST)); - - Long recvRespTime = response.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY) == null ? null - : ((Long) response.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY)); - - Long beforeCallServerTime = - request.getNoneAdditionKv().get(Constants.BEFORE_SERVER_EXECUTE_TIME_KEY) == null ? null - : ((Long) request.getNoneAdditionKv().get(Constants.BEFORE_SERVER_EXECUTE_TIME_KEY)); - - Long serverExecCost = null; - if (beforeCallServerTime != null && recvRespTime != null) { - serverExecCost = recvRespTime - beforeCallServerTime; - } - - LOGGER.info(requestLogFormat, // reqlog - beforeCallServerTime == null ? null : timestampToString(beforeCallServerTime), // reqtime - recvRespTime == null ? null : timestampToString(recvRespTime), // respTime - request.getAttachmentKv().remove(Constants.PROVIDER_APP_NAME_KEY), // remoteName - request.getNoneAdditionKv().get(Constants.REMOTE_ADDRESS_KEY), // remoteAddr - request.getProtocolName(), // protocol - response.getStatus(), // status - request.getNoneAdditionKv().get(Constants.CLIENT_REQUEST_COST), // totalCost - simpleServiceName(request.getServiceName()), // reqServiceName - request.getMethodName(), // reqMethodName - encodeRequestBodyCost, // encodeReqBody - request.getNoneAdditionKv().get(Constants.WAIT_FOR_IO_THREAD_COST_KEY), // waitForIoExec - encodeRequestHeaderCost, // encodeReqHeader - serverExecCost, // serverExecCost - decodeResponseHeaderCost, // decodeRespHeader - waitForThreadCost, // waitForClientThread - decodeResponseBodyCost, // decodeRespBody - traceSpanIdMap.get(TCID), // tid - traceSpanIdMap.get(SPID)); // spid - - LOGGER.debug("[REQLOG] Request logKv {}, Response logKv {}", request.getNoneAdditionKv(), - response.getNoneAdditionKv()); - } catch (Exception e) { - LOGGER.warn("Record server access log error, cause by {}", e.getMessage()); - } - } - - /** - * 请求已经超时后收到了响应,打印响应信息,并推断超时原因 - * - * @param response - */ - public static void timeoutReqAdditionalLog(Response response) { - try { - String timeoutLog = "[TIMEOUT] Request {} timeout: {}. " + "clientReqTime(approx) {}, " - + "servRecvTime {}, " + "servCost(approx) {}, " + "servMethodExecCost {}, " + "recvTime {}, " - + "decRespHead {}, " + "decRespBody {}, " + "tid {}"; - - String timeoutCause = null; - Object methodExecCostObj = response.getAttachmentKv().get(Constants.EXECUTE_METHOD_COST); - Object reqTimeoutObj = response.getAttachmentKv().get(Constants.REQUEST_TIMEOUT_KEY); - Object servCostObj = response.getAttachmentKv().get(Constants.SERVER_EXEC_COST_KEY); - - Integer requestTimeout = null; - Long methodExecCost = null; - Long serverCost = null; - - if (reqTimeoutObj instanceof Integer && methodExecCostObj instanceof Long) { // 方法执行时间超过超时时间,业务问题 - requestTimeout = (Integer) reqTimeoutObj; - methodExecCost = (Long) methodExecCostObj; - - if (methodExecCost >= requestTimeout) { - timeoutCause = "4801 Biz method execution timeout(" + methodExecCost + ">" + requestTimeout + "ms)"; - } - } - - if (methodExecCostObj instanceof Long && servCostObj instanceof Long && StringUtils.isEmpty(timeoutCause)) { - serverCost = (Long) servCostObj; - methodExecCost = (Long) methodExecCostObj; - - if ((serverCost - methodExecCost) > 1000) { // 差值大于1s,推测实例状态异常导致 - timeoutCause = "4802 Abnormal server instance status(CPU_WAIT_IO, tasks_used or cpu_used)"; - } - } - - Object clientReqTimeObj = response.getAttachmentKv().get(Constants.BEFORE_ENCODE_HEADER_TIME_KEY); - Object servRecvReqTimeObj = response.getAttachmentKv().get(Constants.SERVER_RECEIVE_REQ_TIME_KEY); - Long clientReqTime = null; - Long servRecvReqTime = null; - if (clientReqTimeObj instanceof Long && servRecvReqTimeObj instanceof Long // 不满足上述两个条件,推测收到消息延迟 - && StringUtils.isEmpty(timeoutCause)) { - - clientReqTime = (Long) clientReqTimeObj; - servRecvReqTime = (Long) servRecvReqTimeObj; - long messageDelay = servRecvReqTime - clientReqTime; - if (messageDelay > 1000) { - timeoutCause = "4803 Rpc message delay(" + messageDelay + "ms)"; - } - } - - if (StringUtils.isEmpty(timeoutCause)) { - timeoutCause = "4810 Unknown reason"; - } - - Object recvRespTime = response.getNoneAdditionKv().get(Constants.RECEIVE_BYTE_MSG_TIME_KEY); - Object traceId = response.getAttachmentKv().get(Constants.TRACE_ID_KEY); - - LOGGER.error(timeoutLog, response.getNoneAdditionKv().get(Constants.REMOTE_ADDRESS_KEY), // remote addr - timeoutCause, // timeout reason - clientReqTimeObj instanceof Long ? timestampToString((Long) clientReqTimeObj) : null, // req time - // server recv time - servRecvReqTimeObj instanceof Long ? timestampToString((Long) servRecvReqTimeObj) : null, servCostObj, - methodExecCostObj, - recvRespTime instanceof Long ? LogUtils.timestampToString((Long) recvRespTime) : recvRespTime, - response.getNoneAdditionKv().get(Constants.DECODE_HEADER_COST), - response.getNoneAdditionKv().get(Constants.DECODE_BODY_COST), traceId); - } catch (Throwable e) { - LOGGER.warn("Record server timeout log error, cause by ", e); - } - } - - public static String timestampToString(long timestamp) { - Date date = new Date(timestamp); - DateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); - - return sdf.format(date); - } - - protected static String simpleServiceName(String originServiceName) { - if (!originServiceName.contains(".")) { - return originServiceName; - } - - String[] splitNames = originServiceName.split("\\."); - if (splitNames.length == 1) { - return originServiceName; - } - - return splitNames[splitNames.length - 1]; - } - - public static Map parseTraceIdSpanId(Request request) { - Map traceIdSpanIdMap = new HashMap<>(); - if (request.getAttachmentKv() != null - && request.getAttachmentKv().get(PROBE_SPAN_CONTEXT_KEY) instanceof String) { - - traceIdSpanIdMap = probeSpanContextToMap((String) request.getAttachmentKv().get(PROBE_SPAN_CONTEXT_KEY)); - } - - return traceIdSpanIdMap; - } - - protected static Map probeSpanContextToMap(String traceSpanContext) { - - Map traceSpanMap = new HashMap<>(); - - if (StringUtils.isBlank(traceSpanContext)) { - return traceSpanMap; - } - - if (traceSpanContext.endsWith(AND_CHARACTER)) { - traceSpanContext = traceSpanContext.substring(0, traceSpanContext.length() - 1); - } - - // traceSpanContext -> tcid=6d4eecaf-5fcf-11eb-9e5c-3d7693ec528c&spid=6d4eecae-5fcf-11eb-9e5c-3d7693ec528c&xx - - if (!traceSpanContext.contains("tcid") || !traceSpanContext.contains("spid")) { - return traceSpanMap; - } - - String[] traceSpans = traceSpanContext.split(AND_CHARACTER); - if (traceSpans.length < 2) { - return traceSpanMap; - } - - String[] traceInfos = traceSpans[0].split(EQUAL_CHARACTER); - if (traceInfos.length == 2) { - traceSpanMap.put(traceInfos[0], traceInfos[1]); - } - String[] spanInfos = traceSpans[1].split(EQUAL_CHARACTER); - if (spanInfos.length == 2) { - traceSpanMap.put(spanInfos[0], spanInfos[1]); - } - - return traceSpanMap; - } - -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/NetUriUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/NetUriUtils.java deleted file mode 100644 index aa4513ff..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/NetUriUtils.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.UnknownHostException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by liuruisen on 2020/1/16. - */ -public class NetUriUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(NetUriUtils.class); - - private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)"); - - /** - * The Constant IP_PATTERN. - */ - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); - - // cache - private static InetAddress LOCAL_ADDRESS = null; - - private static String localHostIp = null; - - public static Map parseQueryString(String qs) { - if (qs == null || qs.length() == 0) { - return new HashMap(); - } - return parseKeyValuePair(qs, "\\&"); - } - - private static Map parseKeyValuePair(String str, String itemSeparator) { - String[] tmp = str.split(itemSeparator); - Map map = new HashMap(tmp.length); - for (int i = 0; i < tmp.length; i++) { - Matcher matcher = KVP_PATTERN.matcher(tmp[i]); - if (matcher.matches() == false) { - continue; - } - map.put(matcher.group(1), matcher.group(2)); - } - return map; - } - - public static String toQueryString(Map ps) { - StringBuilder buf = new StringBuilder(); - if (ps != null && ps.size() > 0) { - for (Map.Entry entry : new TreeMap(ps).entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (key != null && key.length() > 0 && value != null && value.length() > 0) { - if (buf.length() > 0) { - buf.append("&"); - } - buf.append(key); - buf.append("="); - buf.append(value); - } - } - } - return buf.toString(); - } - - public static String getIpByHost(String hostName) { - try { - return InetAddress.getByName(hostName).getHostAddress(); - } catch (UnknownHostException e) { - return hostName; - } - } - - public static synchronized String getLocalHost() { - // get from cache - if (!StringUtils.isEmpty(localHostIp)) { - return localHostIp; - } - - // get from env - if (EnvUtils.isJarvisEnv()) { - if (!StringUtils.isEmpty(System.getenv(Constants.EM_IP))) { - localHostIp = System.getenv(Constants.EM_IP); - return localHostIp; - } - - if (!StringUtils.isEmpty(System.getenv(Constants.MATRIX_HOST_IP))) { - localHostIp = System.getenv(Constants.MATRIX_HOST_IP); - return localHostIp; - } - } - - // get from NetworkInterface - if (LOCAL_ADDRESS == null) { - LOCAL_ADDRESS = getLocalAddress(); - } - localHostIp = LOCAL_ADDRESS.getHostAddress(); - - return localHostIp; - } - - /** - * Get local address Use real IP first, localhost second - * - * @return - */ - public static InetAddress getLocalAddress() { - InetAddress localAddress = null; - try { - localAddress = InetAddress.getLocalHost(); - if (isValidAddress(localAddress)) { - return localAddress; - } - - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - if (interfaces != null) { - while (interfaces.hasMoreElements()) { - NetworkInterface network = interfaces.nextElement(); - Enumeration addresses = network.getInetAddresses(); - - while (addresses.hasMoreElements()) { - InetAddress address = addresses.nextElement(); - if (isValidAddress(address)) { - return address; - } - } - } - } - } catch (Throwable e) { - LOGGER.warn("Failed to retrieve ip address.", e); - } - LOGGER.error("Failed to get local host ip address, use 127.0.0.1 instead."); - return localAddress; - } - - /** - * check if is a valid address 1. not null 2. not loopbackip 3. not 0.0.0.0 or 127.0.0.1 - * - * @param address - * @return the address is valid or not - */ - public static boolean isValidAddress(InetAddress address) { - if (address == null || address.isLoopbackAddress()) { - return false; - } - - String addressName = address.getHostAddress(); - return (addressName != null && !addressName.equals(Constants.ANYHOST_VALUE) - && !addressName.equals(Constants.LOCALHOST_VALUE) && IP_PATTERN.matcher(addressName).matches()); - } -} diff --git a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/StringUtils.java b/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/StringUtils.java deleted file mode 100644 index a2faeac3..00000000 --- a/starlight/starlight-api/src/main/java/com/baidu/cloud/starlight/api/utils/StringUtils.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import java.util.regex.Pattern; - -/** - * String Utils - */ -public class StringUtils { - private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$"); - - public static final int INDEX_NOT_FOUND = -1; - - private StringUtils() { - - } - - public static int parseInteger(String str) { - if (!isInteger(str)) { - return 0; - } - return Integer.parseInt(str); - } - - public static boolean isInteger(String str) { - if (str == null || str.length() == 0) { - return false; - } - return INT_PATTERN.matcher(str).matches(); - } - - public static boolean isDigits(final String str) { - if (StringUtils.isEmpty(str)) { - return false; - } - for (int i = 0; i < str.length(); i++) { - if (!Character.isDigit(str.charAt(i))) { - return false; - } - } - return true; - } - - public static boolean isEquals(String s1, String s2) { - if (s1 == null && s2 == null) { - return true; - } - if (s1 == null || s2 == null) { - return false; - } - - return s1.equals(s2); - } - - /** - * - *

-     * StringUtils.hasLength(null) = false
-     * StringUtils.hasLength("") = false
-     * StringUtils.hasLength(" ") = true
-     * StringUtils.hasLength("Hello") = true
-     * 
- * - * @param str (may be null) - * @return true if the CharSequence is not null and has length - * @see #hasText(String) - */ - public static boolean hasLength(CharSequence str) { - return (str != null && str.length() > 0); - } - - /** - * @param str (may be null) - * @return true if the String is not null and has length - * @see #hasLength(CharSequence) - */ - public static boolean hasLength(String str) { - return hasLength((CharSequence) str); - } - - /** - * - *
-     * StringUtils.hasText(null) = false
-     * StringUtils.hasText("") = false
-     * StringUtils.hasText(" ") = false
-     * StringUtils.hasText("12345") = true
-     * StringUtils.hasText(" 12345 ") = true
-     * 
- * - * @param str (may be null) - * @return true if the CharSequence is not null, its length is greater than 0, and it does - * not contain whitespace only - */ - public static boolean hasText(CharSequence str) { - if (!hasLength(str)) { - return false; - } - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - /** - * @return true if the String is not null, its length is greater than 0, and it does not - * contain whitespace only - * @see #hasText(CharSequence) - */ - public static boolean hasText(String str) { - return hasText((CharSequence) str); - } - - /** - *

- * Checks if the String contains only unicode digits. A decimal point is not a unicode digit and returns false. - *

- * - *

- * null will return false. An empty String (length()=0) will return true. - *

- * - *
-     * StringUtils.isNumeric(null)   = false
-     * StringUtils.isNumeric("")     = true
-     * StringUtils.isNumeric("  ")   = false
-     * StringUtils.isNumeric("123")  = true
-     * StringUtils.isNumeric("12 3") = false
-     * StringUtils.isNumeric("ab2c") = false
-     * StringUtils.isNumeric("12-3") = false
-     * StringUtils.isNumeric("12.3") = false
-     * 
- * - * @param str the String to check, may be null - * @return true if only contains digits, and is non-null - */ - public static boolean isNumeric(String str) { - if (str == null) { - return false; - } - int sz = str.length(); - for (int i = 0; i < sz; i++) { - if (Character.isDigit(str.charAt(i)) == false) { - return false; - } - } - return true; - } - - public static final String EMPTY = ""; - - public static boolean isEmpty(String str) { - return str == null || str.length() == 0; - } - - public static String substringAfterLast(String str, String separator) { - if (isEmpty(str)) { - return str; - } - if (isEmpty(separator)) { - return EMPTY; - } - int pos = str.lastIndexOf(separator); - if (pos == -1 || pos == (str.length() - separator.length())) { - return EMPTY; - } - return str.substring(pos + separator.length()); - } - - public static String substringBeforeLast(String str, String separator) { - if (isEmpty(str) || isEmpty(separator)) { - return str; - } - int pos = str.lastIndexOf(separator); - if (pos == -1) { - return str; - } - return str.substring(0, pos); - } - - public static String substringBetween(String str, String open, String close) { - if (str == null || open == null || close == null) { - return null; - } - int start = str.indexOf(open); - if (start != -1) { - int end = str.indexOf(close, start + open.length()); - if (end != -1) { - return str.substring(start + open.length(), end); - } - } - return null; - } - - /** - * Trim all whitespace from the given String: leading, trailing, and inbetween characters. - * - * @param str the String to check - * @return the trimmed String - * @see Character#isWhitespace - */ - public static String trimAllWhitespace(String str) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - int index = 0; - while (sb.length() > index) { - if (Character.isWhitespace(sb.charAt(index))) { - sb.deleteCharAt(index); - } else { - index++; - } - } - return sb.toString(); - } - - /** - *

- * Checks if a CharSequence is whitespace, empty ("") or null. - *

- * - *
-     * StringUtils.isBlank(null)      = true
-     * StringUtils.isBlank("")        = true
-     * StringUtils.isBlank(" ")       = true
-     * StringUtils.isBlank("bob")     = false
-     * StringUtils.isBlank("  bob  ") = false
-     * 
- * - * @param cs the CharSequence to check, may be null - * @return {@code true} if the CharSequence is null, empty or whitespace - * @since 2.0 - * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) - */ - public static boolean isBlank(final CharSequence cs) { - int strLen; - if (cs == null || (strLen = cs.length()) == 0) { - return true; - } - for (int i = 0; i < strLen; i++) { - if (Character.isWhitespace(cs.charAt(i)) == false) { - return false; - } - } - return true; - } - - /** - *

- * Removes control characters (char <= 32) from both ends of this String returning an empty String ("") if the - * String is empty ("") after the trim or if it is {@code null}. - * - *

- * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip - * whitespace use {@link #trimToEmpty(String)}. - *

- * - *
-     * StringUtils.trimToEmpty(null)          = ""
-     * StringUtils.trimToEmpty("")            = ""
-     * StringUtils.trimToEmpty("     ")       = ""
-     * StringUtils.trimToEmpty("abc")         = "abc"
-     * StringUtils.trimToEmpty("    abc    ") = "abc"
-     * 
- * - * @param str the String to be trimmed, may be null - * @return the trimmed String, or an empty String if {@code null} input - * @since 2.0 - */ - public static String trimToEmpty(final String str) { - return str == null ? EMPTY : str.trim(); - } - - // SubStringAfter/SubStringBefore - // ----------------------------------------------------------------------- - /** - *

- * Gets the substring before the first occurrence of a separator. The separator is not returned. - *

- * - *

- * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A - * {@code null} separator will return the input string. - *

- * - *

- * If nothing is found, the string input is returned. - *

- * - *
-     * StringUtils.substringBefore(null, *)      = null
-     * StringUtils.substringBefore("", *)        = ""
-     * StringUtils.substringBefore("abc", "a")   = ""
-     * StringUtils.substringBefore("abcba", "b") = "a"
-     * StringUtils.substringBefore("abc", "c")   = "ab"
-     * StringUtils.substringBefore("abc", "d")   = "abc"
-     * StringUtils.substringBefore("abc", "")    = ""
-     * StringUtils.substringBefore("abc", null)  = "abc"
-     * 
- * - * @param str the String to get a substring from, may be null - * @param separator the String to search for, may be null - * @return the substring before the first occurrence of the separator, {@code null} if null String input - * @since 2.0 - */ - public static String substringBefore(final String str, final String separator) { - if (isEmpty(str) || separator == null) { - return str; - } - if (isEmpty(separator)) { - return EMPTY; - } - final int pos = str.indexOf(separator); - if (pos == INDEX_NOT_FOUND) { - return str; - } - return str.substring(0, pos); - } - - /** - *

- * Gets the substring after the first occurrence of a separator. The separator is not returned. - *

- * - *

- * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A - * {@code null} separator will return the empty string if the input string is not {@code null}. - *

- * - *

- * If nothing is found, the empty string is returned. - *

- * - *
-     * StringUtils.substringAfter(null, *)      = null
-     * StringUtils.substringAfter("", *)        = ""
-     * StringUtils.substringAfter(*, null)      = ""
-     * StringUtils.substringAfter("abc", "a")   = "bc"
-     * StringUtils.substringAfter("abcba", "b") = "cba"
-     * StringUtils.substringAfter("abc", "c")   = ""
-     * StringUtils.substringAfter("abc", "d")   = ""
-     * StringUtils.substringAfter("abc", "")    = "abc"
-     * 
- * - * @param str the String to get a substring from, may be null - * @param separator the String to search for, may be null - * @return the substring after the first occurrence of the separator, {@code null} if null String input - * @since 2.0 - */ - public static String substringAfter(final String str, final String separator) { - if (isEmpty(str)) { - return str; - } - if (separator == null) { - return EMPTY; - } - final int pos = str.indexOf(separator); - if (pos == INDEX_NOT_FOUND) { - return EMPTY; - } - return str.substring(pos + separator.length()); - } - - /** - *

- * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring - * case. - *

- * - *

- * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. Comparison is - * case insensitive. - *

- * - *
-     * StringUtils.equalsIgnoreCase(null, null)   = true
-     * StringUtils.equalsIgnoreCase(null, "abc")  = false
-     * StringUtils.equalsIgnoreCase("abc", null)  = false
-     * StringUtils.equalsIgnoreCase("abc", "abc") = true
-     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
-     * 
- * - * @param str1 the first CharSequence, may be null - * @param str2 the second CharSequence, may be null - * @return {@code true} if the CharSequence are equal, case insensitive, or both {@code null} - * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, - * CharSequence) - */ - public static boolean equalsIgnoreCase(final String str1, final String str2) { - if (str1 == null || str2 == null) { - return str1 == str2; - } else if (str1 == str2) { - return true; - } else if (str1.length() != str2.length()) { - return false; - } else { - return str1.equalsIgnoreCase(str2); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/common/URITest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/common/URITest.java deleted file mode 100644 index bfd1a4bd..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/common/URITest.java +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.common; - -import com.baidu.cloud.starlight.api.utils.CollectionUtils; -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class URITest { - - public String baseUriString = "brpc://admin:hello1234@10.20.30.40:20880/context/path?app=mail"; - - public URI baseUri = URI.valueOf(baseUriString); - - public enum STAR { - red, blue - } - - @Test - public void test_valueOf_noProtocolAndHost() throws Exception { - URI uri = URI.valueOf("/context/path?version=1.0.0&app=mail"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = URI.valueOf("context/path?version=1.0.0&app=mail"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("context", uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - } - - @Test - public void test_valueOf_noProtocol() throws Exception { - URI uri = URI.valueOf("10.20.30.40"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals(null, uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("10.20.30.40:20880"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals(null, uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("10.20.30.40/context/path"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("10.20.30.40:20880/context/path"); - assertNull(uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail"); - assertNull(uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - } - - @Test - public void test_valueOf_noHost() throws Exception { - URI uri = URI.valueOf("file:///home/user1/router.js"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("home/user1/router.js", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("file://home/user1/router.js"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("home", uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("user1/router.js", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("file:/home/user1/router.js"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("home/user1/router.js", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("file:///d:/home/user1/router.js"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("d:/home/user1/router.js", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("file:///home/user1/router.js?p1=v1&p2=v2"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("home/user1/router.js", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - Map params = new HashMap(); - params.put("p1", "v1"); - params.put("p2", "v2"); - assertEquals(params, uri.getParameters()); - - uri = URI.valueOf("file:/home/user1/router.js?p1=v1&p2=v2"); - assertEquals("file", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertNull(uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals("home/user1/router.js", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - params = new HashMap(); - params.put("p1", "v1"); - params.put("p2", "v2"); - assertEquals(params, uri.getParameters()); - } - - @Test - public void test_valueOf_WithProtocolHost() throws Exception { - URI uri = URI.valueOf("brpc://10.20.30.40"); - assertEquals("brpc", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(0, uri.getPort()); - assertEquals(null, uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("brpc://10.20.30.40:20880/context/path"); - assertEquals("brpc", uri.getProtocol()); - assertNull(uri.getUsername()); - assertNull(uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals(null, uri.getPath()); - assertEquals(0, uri.getParameters().size()); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880?version=1.0.0"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals(null, uri.getPath()); - assertEquals(1, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail&noValue"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - assertEquals("noValue", uri.getParameter("noValue")); - } - - @Test - public void test_valueOf_Exception_noProtocol() throws Exception { - try { - URI.valueOf("://1.2.3.4:8080/path"); - fail(); - } catch (IllegalStateException expected) { - assertEquals("uri missing protocol: \"://1.2.3.4:8080/path\"", expected.getMessage()); - } - } - - @Test - public void test_getAddress() throws Exception { - URI uri1 = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail"); - assertEquals("10.20.30.40:20880", uri1.getAddress()); - } - - @Test - public void test_getAbsolutePath() throws Exception { - URI uri = new URI.Builder("p1", "1.2.2.2", 33).build(); - assertEquals(null, uri.getAbsolutePath()); - - uri = new URI.Builder("file", null, 33).path("/home/user1/route.js").build(); - assertEquals("/home/user1/route.js", uri.getAbsolutePath()); - } - - @Test - public void test_equals() throws Exception { - URI uri1 = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail"); - - Map params = new HashMap(); - params.put("version", "1.0.0"); - params.put("app", "mail"); - URI uri2 = new URI.Builder("brpc", "10.20.30.40", 20880).path("context/path").params(params).build(); - assertEquals(uri1, uri2); - - URI uri3 = - URI.valueOf("brpc://10.95.105.153:3002?executes=50&group=test_dev&interface=" + "demo.v3.HelloWorldService" - + "&interface.simple=HelloWorldService®istry=default&brccgate.version=1.2.15" + "&version=1.0.0"); - URI uri4 = URI.valueOf("brpc://10.95.105.153:3002?executes=50&group=test_dev&interface=demo.v3.DemoService" - + "&interface.simple=DemoService®istry=default&brpcgate.version=1.2.15&version=1.0.0"); - System.out.println(uri3.hashCode()); - System.out.println(uri3.hashCode()); - System.out.println(uri3.equals(uri4)); - } - - @Test - public void test_toString() throws Exception { - URI uri1 = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0"); - assertEquals(uri1.toString(), "brpc://10.20.30.40:20880/context/path?version=1.0.0"); - } - - @Test - public void test_toFullString() throws Exception { - assertEquals(baseUri.toFullString(), baseUriString); - } - - @Test - public void test_toIdentityString() throws Exception { - assertEquals(baseUri.toIdentityString(), "brpc://admin:hello1234@10.20.30.40:20880/context/path"); - } - - @Test - public void test_toParameterString() throws Exception { - URI uri1 = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?app=mail&k1=v1"); - - assertEquals(uri1.toParameterString(), "app=mail&k1=v1"); - } - - @Test - public void test_set_methods() throws Exception { - URI uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail"); - - uri = uri.resetHost("host"); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = uri.resetPort(1); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(1, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = uri.resetPath("path"); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(1, uri.getPort()); - assertEquals("path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = uri.resetProtocol("protocol"); - - assertEquals("protocol", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(1, uri.getPort()); - assertEquals("path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = uri.resetUsername("username"); - - assertEquals("protocol", uri.getProtocol()); - assertEquals("username", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(1, uri.getPort()); - assertEquals("path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - - uri = uri.resetPassword("password"); - - assertEquals("protocol", uri.getProtocol()); - assertEquals("username", uri.getUsername()); - assertEquals("password", uri.getPassword()); - assertEquals("host", uri.getHost()); - assertEquals(1, uri.getPort()); - assertEquals("path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("1.0.0", uri.getParameter("version")); - assertEquals("mail", uri.getParameter("app")); - } - - @Test - public void test_removeParameters() throws Exception { - URI uri = - URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail&k1=v1&k2=v2"); - - uri = uri.removeParameter("version"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("mail", uri.getParameter("app")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail&k1=v1&k2=v2"); - uri = uri.removeParameters("version", "app"); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = URI.valueOf("brpc://admin:hello1234@10.20.30.40:20880/context/path?version=1.0.0&app=mail&k1=v1&k2=v2"); - uri = uri.removeParameters(Arrays.asList("version", "app")); - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(2, uri.getParameters().size()); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - uri = uri.clearParameters(); - assertEquals("", uri.toParameterString()); - } - - @Test - public void test_addParameters() throws Exception { - URI uri = baseUri.addParameters(CollectionUtils.toStringMap("k1", "v1", "k2", "v2")); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("mail", uri.getParameter("app")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = baseUri.addParameters("k1", "v1", "k2", "v2", "app", "xxx"); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("xxx", uri.getParameter("app")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = baseUri.addParametersIfAbsent(CollectionUtils.toStringMap("k1", "v1", "k2", "v2", "app", "xxx")); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("mail", uri.getParameter("app")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = baseUri.addParameterString("k1=v1&k2=v2"); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(3, uri.getParameters().size()); - assertEquals("mail", uri.getParameter("app")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - - uri = new URI.Builder(baseUri).param("app", "xxx").build(); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(1, uri.getParameters().size()); - assertEquals("xxx", uri.getParameter("app")); - - uri = new URI.Builder(baseUri).paramIfAbsent("app", "xxx").build(); - - assertEquals("brpc", uri.getProtocol()); - assertEquals("admin", uri.getUsername()); - assertEquals("hello1234", uri.getPassword()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("context/path", uri.getPath()); - assertEquals(1, uri.getParameters().size()); - assertEquals("mail", uri.getParameter("app")); - } - - @Test - public void test_otherMethod() throws Exception { - URI uri = new URI.Builder(baseUriString).paramString("group=test&version=1.0&interface=com.baidu.test").build(); - - assertEquals("test:com.baidu.test:1.0", uri.getServiceKey()); - assertEquals("com.baidu.test", uri.getServiceName()); - assertEquals(new InetSocketAddress("10.20.30.40", 20880), uri.toInetSocketAddress()); - assertEquals("10.20.30.40", uri.getIp()); - - } - - @Test - public void test_getParameters() throws Exception { - URI uri = new URI.Builder(baseUriString).param("s", "bad").param("i", 999).param("b", true).param("d", 9.9) - .param("l", 9999l).param("I", new Integer(998)).param("Ered", STAR.red).param("arr", "ss,ff,nn") - .username("user").password("userpasswd").params("k1", "v1", "k2", "v2").paramString("k3=v3&k4=v4") - .param("m.arr", "ss,ff,nn") - .paramString("m.k3=v33&m.k4=v44&m.i=123&m.l=123&m.d=2.123&m.b=false&m.s=mgood&m.s1=mgood1") - .paramString("fd=-9.9&fi=-9&fl=-99").paramAndEncoded("china", "[当代").build(); - assertEquals("userpasswd", uri.getPassword()); - assertEquals("brpc", uri.getProtocol()); - assertEquals(999, uri.getParameter("i", 888)); - assertEquals(888, uri.getParameter("i2", 888)); - assertEquals("bad", uri.getParameter("s")); - assertEquals("bad", uri.getParameter("s", "good")); - assertEquals("good", uri.getParameter("ss", "good")); - assertArrayEquals(new String[] {"ss", "ff", "nn"}, uri.getParameter("arr", new String[] {"ss", "uu"})); - assertArrayEquals(new String[] {"ss", "uu"}, uri.getParameter("strarr2", new String[] {"ss", "uu"})); - assertEquals(9.9, uri.getParameter("d", 8.8), 0.1); - assertEquals(8.8, uri.getParameter("d2", 8.8), 0.1); - assertEquals(9999l, uri.getParameter("l", 8888l)); - assertEquals(8888l, uri.getParameter("l2", 8888l)); - assertEquals("true", uri.getParameter("b")); - assertEquals(true, uri.getParameter("b", false)); - assertEquals(false, uri.getParameter("bfalse", false)); - assertEquals("998", uri.getParameter("I")); - assertEquals("red", uri.getParameter("Ered")); - assertEquals("v1", uri.getParameter("k1")); - assertEquals("v2", uri.getParameter("k2")); - assertEquals("v3", uri.getParameter("k3")); - assertEquals("v4", uri.getParameter("k4")); - assertEquals("v33", uri.getMethodParameter("m", "k3")); - assertEquals("v1", uri.getMethodParameter("m", "k1")); - assertEquals("v44", uri.getMethodParameter("m", "k4")); - assertEquals(123, uri.getMethodParameter("m", "i", 124)); - assertEquals(123l, uri.getMethodParameter("m", "l", 124l)); - assertEquals(2.123d, uri.getMethodParameter("m", "d", 2.123), 0.1); - assertEquals(false, uri.getMethodParameter("m", "b", true)); - assertEquals("mgood", uri.getMethodParameter("m", "s", "mgood")); - assertEquals(true, uri.hasMethodParameter("m", "s1")); - assertEquals(false, uri.hasMethodParameter(null, null)); - assertEquals(false, uri.hasParameter("s2")); - assertEquals(1000.0, uri.getPositiveParameter("fd", 1000.0), 0.1); - assertEquals(1000, uri.getPositiveParameter("fi", 1000)); - assertEquals(1000l, uri.getPositiveParameter("fl", 1000l)); - assertEquals("[当代", uri.getMethodParameterAndDecoded("m", "china")); - assertEquals("[当代", uri.getMethodParameterAndDecoded("m", "china1", "[当代")); - assertEquals("[当代", uri.getParameterAndDecoded("china", "china")); - assertEquals("[当代", uri.getParameterAndDecoded("china")); - } - - @Test - public void test_windowAbsolutePathBeginWithSlashIsValid() throws Exception { - final String osProperty = System.getProperties().getProperty("os.name"); - if (!osProperty.toLowerCase().contains("windows")) - return; - - File f0 = new File("C:/Windows"); - File f1 = new File("/C:/Windows"); - - File f2 = new File("C:\\Windows"); - File f3 = new File("/C:\\Windows"); - File f4 = new File("\\C:\\Windows"); - - assertEquals(f0, f1); - assertEquals(f0, f2); - assertEquals(f0, f3); - assertEquals(f0, f4); - } - - @Test - public void test_javaNetUrl() throws Exception { - java.net.URL uri = - URI.valueOf("http://admin:hello1234@10.20.30.40:20880/context/path?app=mail&version=1.0.0#anchor1") - .toJavaURL(); - - assertEquals("http", uri.getProtocol()); - assertEquals("admin:hello1234", uri.getUserInfo()); - assertEquals("10.20.30.40", uri.getHost()); - assertEquals(20880, uri.getPort()); - assertEquals("/context/path", uri.getPath()); - assertEquals("app=mail&version=1.0.0", uri.getQuery()); - assertEquals("anchor1", uri.getRef()); - - assertEquals("admin:hello1234@10.20.30.40:20880", uri.getAuthority()); - assertEquals("/context/path?app=mail&version=1.0.0", uri.getFile()); - } - - @Test - public void test_builder_param_null() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - builder.param("key", ""); // param string string null - builder.paramString(""); // paramString blank - builder.paramAndEncoded("key2", ""); // paramAndEncoded blank - builder.paramIfAbsent("key3", ""); // paramIfAbsent blank - } - - @Test - public void test_uri_illegal() { - // username not exist but have password - try { - URI uri = new URI("brpc", "", "123qwe", "0.0.0.0", 8888, "/context", new HashMap<>()); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalArgumentException); - } - - // port 0 - URI uri = new URI("brpc", "name", "123qwe", "0.0.0.0", 0, "/context", new HashMap<>()); - Assert.assertEquals(uri.getPort(), 0); - } - - @Test - public void encode_decode() { - String msg1 = URI.encode(null); - Assert.assertEquals(msg1, ""); - String msg2 = URI.decode(null); - Assert.assertEquals(msg2, ""); - String encodeMsg = URI.encode("你好啊"); - Assert.assertEquals(URI.decode(encodeMsg), "你好啊"); - } - - @Test - public void equals() { - URI uri = new URI("brpc", "name", "123qwe", "0.0.0.0", 8888, "/context", new HashMap<>()); - - URI uri2 = - new URI("brpc", "name", "123qwe", "0.0.0.0", 8888, "/context", Collections.singletonMap("key", "value")); - - Assert.assertTrue(uri.equals(uri2)); - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/Ext1.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/Ext1.java deleted file mode 100644 index 56e1eb27..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/Ext1.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -import com.baidu.cloud.starlight.api.common.URI; - -public interface Ext1 { - String echo(URI uri, String s); - - String yell(URI uri, String s); - - String bang(URI uri, int i); -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/ExtensionLoaderTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/ExtensionLoaderTest.java deleted file mode 100644 index 9442f0d4..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/ExtensionLoaderTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension; - -import com.baidu.cloud.starlight.api.extension.impl.Ext1Impl1; -import com.baidu.cloud.starlight.api.extension.impl.Ext1Impl2; -import com.baidu.cloud.starlight.api.extension.impl.Ext1Impl3; -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class ExtensionLoaderTest { - - @Test - public void test_getExtension() throws Exception { - assertTrue(ExtensionLoader.getInstance(Ext1.class).getExtension("impl1") instanceof Ext1Impl1); - assertTrue(ExtensionLoader.getInstance(Ext1.class).getExtension("impl2") instanceof Ext1Impl2); - assertTrue(ExtensionLoader.getInstance(Ext1.class).getExtension("xxx") instanceof Ext1Impl3); - } - - @Test - public void test_getExtension_Run() throws Exception { - String[] impls = new String[] {"impl1", "impl2", "xxx"}; - int i = 1; - for (String impl : impls) { - Ext1 x = ExtensionLoader.getInstance(Ext1.class).getExtension(impl); - assertEquals("bang" + i++, x.bang(null, 1)); - assertTrue(ExtensionLoader.getInstance(Ext1.class).hasExtension(impl)); - } - - assertEquals("impl1", ExtensionLoader.getInstance(Ext1.class).getExtensionName(new Ext1Impl1())); - assertArrayEquals(impls, ExtensionLoader.getInstance(Ext1.class).getLoadedExtensions().toArray(new String[0])); - assertArrayEquals(impls, - ExtensionLoader.getInstance(Ext1.class).getSupportedExtensions().toArray(new String[0])); - assertEquals(ExtensionLoader.class.getName() + "[" + Ext1.class.getName() + "]", - ExtensionLoader.getInstance(Ext1.class).toString()); - - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl1.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl1.java deleted file mode 100644 index ae17913b..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl1.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension.impl; - -import com.baidu.cloud.starlight.api.extension.Ext1; -import com.baidu.cloud.starlight.api.common.URI; - -public class Ext1Impl1 implements Ext1 { - public String echo(URI uri, String s) { - return "echo1"; - } - - public String yell(URI uri, String s) { - return "yell1"; - } - - public String bang(URI uri, int i) { - return "bang1"; - } -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl2.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl2.java deleted file mode 100644 index 476615ce..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl2.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension.impl; - -import com.baidu.cloud.starlight.api.extension.Ext1; -import com.baidu.cloud.starlight.api.common.URI; - -public class Ext1Impl2 implements Ext1 { - public String echo(URI uri, String s) { - return "echo2"; - } - - public String yell(URI uri, String s) { - return "yell2"; - } - - public String bang(URI uri, int i) { - return "bang2"; - } -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl3.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl3.java deleted file mode 100644 index 1761c16c..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/extension/impl/Ext1Impl3.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.extension.impl; - -import com.baidu.cloud.starlight.api.extension.Ext1; -import com.baidu.cloud.starlight.api.common.URI; - -public class Ext1Impl3 implements Ext1 { - public String echo(URI uri, String s) { - return "echo3"; - } - - public String yell(URI uri, String s) { - return "yell3"; - } - - public String bang(URI uri, int i) { - return "bang3"; - } -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ExtInfo.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ExtInfo.java deleted file mode 100644 index b43f1a05..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ExtInfo.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -public class ExtInfo { - private String key; - - private Object value; - - public ExtInfo(String key, Object value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ExtInfo{"); - sb.append("key='").append(key).append('\''); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ResultFutureTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ResultFutureTest.java deleted file mode 100644 index ea07fde8..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/ResultFutureTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class ResultFutureTest { - - private Response response; - - @Before - public void before() { - response = new RpcResponse(); - response.setResult("111"); - response.setStatus(Constants.SUCCESS_CODE); - } - - @Test - public void putResponse() throws ExecutionException, InterruptedException { - ResultFuture resultFuture = new ResultFuture(); - resultFuture.putResponse(response); - Assert.assertEquals(resultFuture.get(), "111"); - Assert.assertTrue(resultFuture.isDone()); - Assert.assertTrue(resultFuture.isCancelled()); - Assert.assertFalse(resultFuture.cancel(true)); - } - - @Test - public void testGet() throws InterruptedException, ExecutionException, TimeoutException { - ResultFuture resultFuture = new ResultFuture(); - resultFuture.putResponse(response); - Assert.assertEquals(resultFuture.get(100, TimeUnit.MILLISECONDS), "111"); - } - - @Test - public void testGetError() throws InterruptedException, ExecutionException, TimeoutException { - ResultFuture resultFuture = new ResultFuture(); - Response response = new RpcResponse(); - response.setStatus(1000); - response.setErrorMsg("Error"); - resultFuture.putResponse(response); - try { - resultFuture.get(100, TimeUnit.MILLISECONDS); - } catch (StarlightRpcException e) { - Assert.assertTrue(e.getCode() == 1000); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/RpcRequestTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/RpcRequestTest.java deleted file mode 100644 index 9af159e3..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/RpcRequestTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Created by liuruisen on 2020/7/30. - */ -public class RpcRequestTest { - - @Test - public void getServiceName() { - RpcRequest request = new RpcRequest(); - request.setServiceClass(RpcRequest.class); - request.setServiceConfig(new ServiceConfig()); - - assertEquals(RpcRequest.class.getName(), request.getServiceName()); - - request.setServiceName("serviceName"); - assertEquals("serviceName", request.getServiceName()); - - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/User.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/User.java deleted file mode 100644 index 3f9486ca..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/model/User.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.model; - -import java.util.List; - -/** - * Created by liuruisen on 2020/3/6. - */ -public class User { - - private long userId; - - private String userName; - - private double balance; - - private List tags; - - private List extInfos; - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public List getExtInfos() { - return extInfos; - } - - public void setExtInfos(List extInfos) { - this.extInfos = extInfos; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("User{"); - sb.append("userId=").append(userId); - sb.append(", userName='").append(userName).append('\''); - sb.append(", balance=").append(balance); - sb.append(", tags=").append(tags); - sb.append(", extInfos=").append(extInfos); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoderTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoderTest.java deleted file mode 100644 index 18aa3dcb..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/protocol/ProtocolEncoderTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.protocol; - -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/5/13. - */ -public class ProtocolEncoderTest { - - @Test - public void addAdditionalRespKv() { - - Response response = new RpcResponse(); - - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcContextTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcContextTest.java deleted file mode 100644 index 239f4cd5..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcContextTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/9/2. - */ -public class RpcContextTest { - - @Test - public void testContext() { - Assert.assertNotNull(RpcContext.getContext()); - Assert.assertNotNull(RpcContext.getContext().get()); - Assert.assertEquals(0, RpcContext.getContext().get().size()); - RpcContext.getContext().set("Key", "Value"); - Assert.assertEquals(1, RpcContext.getContext().get().size()); - Assert.assertEquals("Value", RpcContext.getContext().get().get("Key")); - Map map = new LinkedHashMap<>(); - map.put("Key1", "Value1"); - map.put("Key2", "Value2"); - RpcContext.getContext().set(map); - Assert.assertEquals(2, RpcContext.getContext().get().size()); - Assert.assertEquals("Value2", RpcContext.getContext().get().get("Key2")); - RpcContext.getContext().set(new HashMap<>()); - Assert.assertEquals(0, RpcContext.getContext().get().size()); - RpcContext.removeContext(); - } - - @Test - public void testGetSet() { - RpcContext.getContext().setRequestID("requestId"); - RpcContext.getContext().setSessionID("sessionId"); - RpcContext.getContext().setRemoteAddress("127.0.0.1", 9999); - - assertEquals("requestId", RpcContext.getContext().getRequestID()); - assertEquals("sessionId", RpcContext.getContext().getSessionID()); - assertEquals("127.0.0.1:9999", RpcContext.getContext().getRemoteAddressString()); - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcServiceTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcServiceTest.java deleted file mode 100644 index a8e70331..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/RpcServiceTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc; - -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.service.UserService; -import com.baidu.cloud.starlight.api.service.UserServiceImpl; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class RpcServiceTest { - - private RpcService rpcService; - - @Before - public void before() { - rpcService = new RpcService(UserService.class, new UserServiceImpl()); - } - - @Test - public void getServiceName() { - Assert.assertTrue(rpcService.getServiceName().contains(UserService.class.getName())); - } - - @Test - public void getServiceInterface() { - Assert.assertEquals(rpcService.getServiceClass(), UserService.class); - } - - @Test - public void getServiceObject() { - Assert.assertTrue(rpcService.getServiceObject() instanceof UserServiceImpl); - } - - @Test - public void getMethod() { - Assert.assertNotNull(rpcService.getMethod("getUser")); - } - - @Test - public void getServiceConfig() { - rpcService.setServiceConfig(new ServiceConfig()); - Assert.assertNotNull(rpcService.getServiceConfig()); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfigTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfigTest.java deleted file mode 100644 index 33202a9c..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/rpc/config/ServiceConfigTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.rpc.config; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Created by liuruisen on 2020/7/30. - */ -public class ServiceConfigTest { - - @Test - public void serviceName() { - ServiceConfig serviceConfig = new ServiceConfig(); - - assertEquals(ServiceConfig.class.getName(), serviceConfig.serviceName(ServiceConfig.class)); - - serviceConfig.setServiceId("serviceName"); - assertEquals("serviceName", serviceConfig.serviceName(ServiceConfig.class)); - - serviceConfig.setGroup(""); - serviceConfig.setVersion(""); - serviceConfig.setServiceId(""); - assertEquals(ServiceConfig.class.getName(), serviceConfig.serviceName(ServiceConfig.class)); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/AsyncUserService.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/AsyncUserService.java deleted file mode 100644 index 4af83d57..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/AsyncUserService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.service; - -import com.baidu.cloud.starlight.api.model.User; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; - -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/3/11. - */ -public interface AsyncUserService extends UserService { - - void getUserCallback(Long userId, Callback callback); - - Future getUserFuture(Long userId); -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserService.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserService.java deleted file mode 100644 index 483baa0f..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.service; - -import com.baidu.cloud.starlight.api.model.User; - -/** - * Created by liuruisen on 2020/3/6. - */ -public interface UserService { - - User getUser(Long userId); - - User updateUser(User user); - - void deleteUser(Long userId); - - Long saveUser(User user); -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserServiceImpl.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserServiceImpl.java deleted file mode 100644 index 20f08e5c..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/service/UserServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.service; - -import com.baidu.cloud.starlight.api.model.ExtInfo; -import com.baidu.cloud.starlight.api.model.User; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/6. - */ -public class UserServiceImpl implements UserService { - - @Override - public User getUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - return user; - } - - @Override - public User updateUser(User user) { - return user; - } - - @Override - public void deleteUser(Long userId) { - try { - TimeUnit.SECONDS.sleep(2); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Delete user {" + userId + "}"); - } - - @Override - public Long saveUser(User user) { - return user.getUserId(); - } -} diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtilsTest.java deleted file mode 100644 index 2d2ce742..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/ByteArrayUtilsTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/9. - */ -public class ByteArrayUtilsTest { - - @Test - public void byteMerger() { - byte[] byte1 = "123".getBytes(); - byte[] byte2 = "456".getBytes(); - byte[] result = ByteArrayUtils.byteMerger(byte1, byte2); - Assert.assertTrue(result.length == (byte1.length + byte2.length)); - } - - @Test - public void byteMergerNull() { - byte[] byte1 = null; - byte[] byte2 = "12345".getBytes(); - byte[] result = ByteArrayUtils.byteMerger(null, byte2); - Assert.assertTrue(result.length == byte2.length); - - byte[] result2 = ByteArrayUtils.byteMerger(byte2, null); - Assert.assertTrue(result.length == byte2.length); - - } - - @Test - public void subByte() { - byte[] bytes = "123456".getBytes(); - byte[] result = ByteArrayUtils.subByte(bytes, 2, 4); - Assert.assertTrue(result.length == 4); - - byte[] result2 = ByteArrayUtils.subByte(null, 2, 4); - Assert.assertTrue(result2 == null); - - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/CollectionUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/CollectionUtilsTest.java deleted file mode 100644 index 8c910e28..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/CollectionUtilsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.Map; - -/** - * Created by liuruisen on 2020/3/19. - */ -public class CollectionUtilsTest { - - @Test - public void toStringMap() { - String[] paris = new String[] {"key", "value", "key2", "value2"}; - - Map map = CollectionUtils.toStringMap(paris); - - Assert.assertTrue(map.get("key").equals("value")); - } - - @Test(expected = IllegalArgumentException.class) - public void toStringMapException() { - String[] paris = new String[] {"key", "value", "key2"}; - - Map map = CollectionUtils.toStringMap(paris); - - Assert.assertTrue(map.get("key").equals("value")); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/EnvUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/EnvUtilsTest.java deleted file mode 100644 index 9f2e72f8..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/EnvUtilsTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import org.junit.Rule; -import org.junit.Test; -import org.junit.contrib.java.lang.system.EnvironmentVariables; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/11/17. - */ -public class EnvUtilsTest { - - @Rule - public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); - - @Test - public void getCpuCores() { - - assertEquals(Math.max(Runtime.getRuntime().availableProcessors(), 8), EnvUtils.getCpuCores()); - - environmentVariables.set(Constants.EM_APP, "em-name"); - environmentVariables.set(Constants.EM_PLATFORM, "em-platform"); - environmentVariables.set(Constants.EM_PRODUCT_LINE, "em-product"); - - environmentVariables.set(Constants.EM_CPU_CORES, "100"); - - assertEquals(40, EnvUtils.getCpuCores()); - - environmentVariables.set(Constants.EM_CPU_CORES, "10"); - assertEquals(8, EnvUtils.getCpuCores()); - } - - @Test - public void isJarvisEnv() { - assertFalse(EnvUtils.isJarvisEnv()); - - environmentVariables.set(Constants.EM_APP, "em-name"); - environmentVariables.set(Constants.EM_PLATFORM, "em-platform"); - environmentVariables.set(Constants.EM_PRODUCT_LINE, "em-product"); - - assertTrue(EnvUtils.isJarvisEnv()); - - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/GenericUtilTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/GenericUtilTest.java deleted file mode 100644 index 51a1d565..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/GenericUtilTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by liuruisen on 2020/4/29. - */ -public class GenericUtilTest { - - @Test - public void isGenericCall() { - Request request = new RpcRequest(); - request.setMethodName("$invoke"); - Assert.assertTrue(GenericUtil.isGenericCall(request)); - Assert.assertFalse(GenericUtil.isGenericCall(new RpcRequest())); - } - - @Test - public void markGeneric() { - Request request = new RpcRequest(); - GenericUtil.markGeneric(request); - Assert.assertTrue(request.getAttachmentKv().size() > 0); - Assert.assertTrue((Boolean) request.getAttachmentKv().get(Constants.IS_GENERIC_KEY)); - } - - @Test - public void isGenericMsg() { - Request request = new RpcRequest(); - Assert.assertFalse(GenericUtil.isGenericMsg(request)); - Map map = new HashMap<>(); - map.put(Constants.IS_GENERIC_KEY, Boolean.TRUE); - request.setAttachmentKv(map); - Assert.assertTrue(GenericUtil.isGenericMsg(request)); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IDGeneratorTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IDGeneratorTest.java deleted file mode 100644 index 3fadbaaf..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IDGeneratorTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.junit.Test; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; - -/** - * Created by liuruisen on 2021/7/30. - */ -public class IDGeneratorTest { - - @Test - public void genID() throws InterruptedException { - Map result = new ConcurrentHashMap<>(); - - ExecutorService executorService = Executors.newFixedThreadPool(500); - - for (int i = 0; i < 500; i++) { - executorService.execute(() -> { - IDGenerator generator = IDGenerator.getInstance(); - for (int j = 0; j < (1 << 10); j++) { - result.put(generator.nextId(), 1L); - } - }); - } - - TimeUnit.SECONDS.sleep(30); - assertEquals(500 * (1 << 10), result.size()); - } - - @Test - public void testError() { - Integer intV = 2147483647; - System.out.println(intV); - intV = intV << 8; - System.out.println(intV); - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IdUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IdUtilsTest.java deleted file mode 100644 index ebb834d0..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/IdUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/9/3. - */ -public class IdUtilsTest { - - @Test - public void genUUID() throws InterruptedException { - String uuid = IdUtils.genUUID(); - TimeUnit.MILLISECONDS.sleep(100); - assertNotEquals(uuid, IdUtils.genUUID()); - - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/LogUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/LogUtilsTest.java deleted file mode 100644 index be3e3bb3..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/LogUtilsTest.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/1/8. - */ -public class LogUtilsTest { - - @Test - public void addLogTimeAttachment() { - RpcResponse response = new RpcResponse(); - assertEquals(0, response.getNoneAdditionKv().size()); - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_ENCODE_BODY_TIME_KEY, System.currentTimeMillis()); - assertEquals(1, response.getNoneAdditionKv().size()); - - RpcRequest request = new RpcRequest(); - assertEquals(0, request.getNoneAdditionKv().size()); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_ENCODE_BODY_TIME_KEY, System.currentTimeMillis()); - assertEquals(1, request.getNoneAdditionKv().size()); - } - - @Test - public void recordAccessLog() { - Request request = new RpcRequest(); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_ENCODE_BODY_TIME_KEY, System.currentTimeMillis()); - LogUtils.addLogTimeAttachment(request, Constants.ENCODE_BODY_COST, 12); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_THREAD_EXECUTE_TIME_KEY, System.currentTimeMillis()); - - Response response = new RpcResponse(); - - LogUtils.recordAccessLog(request, response); - - request.setServiceClass(this.getClass()); - LogUtils.recordAccessLog(request, response); - - ServiceConfig serviceConfig = new ServiceConfig(); - request.setServiceConfig(serviceConfig); - LogUtils.recordAccessLog(request, response); - } - - @Test - public void recordRequestLog() { - - Request request = new RpcRequest(); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_ENCODE_BODY_TIME_KEY, System.currentTimeMillis()); - LogUtils.addLogTimeAttachment(request, Constants.ENCODE_BODY_COST, 12); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_THREAD_EXECUTE_TIME_KEY, System.currentTimeMillis()); - - Response response = new RpcResponse(); - - LogUtils.recordRequestLog(request, response); - - request.setServiceClass(this.getClass()); - LogUtils.recordRequestLog(request, response); - - ServiceConfig serviceConfig = new ServiceConfig(); - request.setServiceConfig(serviceConfig); - LogUtils.recordRequestLog(request, response); - - } - - @Test - public void timestampToString() { - - long time = System.currentTimeMillis(); - - System.out.println(LogUtils.timestampToString(time)); - - assertNotNull(LogUtils.timestampToString(time)); - } - - @Test - public void simpleServiceName() { - String serviceId = "starlight-provider"; - - assertEquals("starlight-provider", LogUtils.simpleServiceName(serviceId)); - - String serviceId2 = "starlight."; - assertEquals(serviceId2, LogUtils.simpleServiceName(serviceId2)); - - String serviceName = this.getClass().getName(); - assertEquals(this.getClass().getSimpleName(), LogUtils.simpleServiceName(serviceName)); - - } - - @Test - public void parseTrace() { - Request request = new RpcRequest(); - request.setAttachmentKv(new HashMap<>()); - - Map spanTraceMap = LogUtils.parseTraceIdSpanId(request); - assertNull(spanTraceMap.get(LogUtils.TCID)); - assertNull(spanTraceMap.get(LogUtils.SPID)); - - String info = "tcid=6d4eecaf-5fcf-11eb-9e5c-3d7693ec528c&spid=6d4eecae-5fcf-11eb-9e5c-3d7693ec528c&"; - request.getAttachmentKv().put(LogUtils.PROBE_SPAN_CONTEXT_KEY, info); - spanTraceMap = LogUtils.parseTraceIdSpanId(request); - assertNotNull(spanTraceMap.get(LogUtils.TCID)); - assertNotNull(spanTraceMap.get(LogUtils.SPID)); - - String traceInfo2 = "tcid=6d4eecaf-5fcf-11eb-9e5c-3d7693ec528c&spid=6d4eecae-5fcf-11eb-9e5c-3d7693ec528c" - + "&user_id=4434331950&"; - request.getAttachmentKv().put(LogUtils.PROBE_SPAN_CONTEXT_KEY, traceInfo2); - spanTraceMap = LogUtils.parseTraceIdSpanId(request); - assertNotNull(spanTraceMap.get(LogUtils.TCID)); - assertNotNull(spanTraceMap.get(LogUtils.SPID)); - - String traceInfo3 = "tcid=6d4eecaf-5fcf-11eb-9e5c-3d7693ec528c"; - request.getAttachmentKv().put(LogUtils.PROBE_SPAN_CONTEXT_KEY, traceInfo3); - spanTraceMap = LogUtils.parseTraceIdSpanId(request); - assertNull(spanTraceMap.get(LogUtils.TCID)); - assertNull(spanTraceMap.get(LogUtils.SPID)); - - String traceInfo4 = "spid=6d4eecae-5fcf-11eb-9e5c-3d7693ec528c"; - request.getAttachmentKv().put(LogUtils.PROBE_SPAN_CONTEXT_KEY, traceInfo4); - spanTraceMap = LogUtils.parseTraceIdSpanId(request); - assertNull(spanTraceMap.get(LogUtils.TCID)); - assertNull(spanTraceMap.get(LogUtils.SPID)); - - } - - @Test - public void serverMethodExceedTimeout() { - Response response = new RpcResponse(); - response.getAttachmentKv().put(Constants.REQUEST_TIMEOUT_KEY, 5000); - response.getAttachmentKv().put(Constants.EXECUTE_METHOD_COST, 6000L); - response.getAttachmentKv().put(Constants.SERVER_EXEC_COST_KEY, 6010L); - - long beforeEncodeTime = System.currentTimeMillis(); - response.getAttachmentKv().put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeTime); - response.getAttachmentKv().put(Constants.SERVER_RECEIVE_REQ_TIME_KEY, beforeEncodeTime + 10); - response.getAttachmentKv().put(Constants.TRACE_ID_KEY, "123456789"); - - response.getNoneAdditionKv().put(Constants.RECEIVE_BYTE_MSG_TIME_KEY, beforeEncodeTime + 6010 + 10); - response.getNoneAdditionKv().put(Constants.DECODE_HEADER_COST, 1L); - response.getNoneAdditionKv().put(Constants.DECODE_BODY_COST, 1L); - response.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, "localhost:9090"); - - LogUtils.timeoutReqAdditionalLog(response); - } - - @Test - public void instanceStatusAbnormalTimeout() { - Response response = new RpcResponse(); - response.getAttachmentKv().put(Constants.REQUEST_TIMEOUT_KEY, 5000); - response.getAttachmentKv().put(Constants.EXECUTE_METHOD_COST, 600L); - response.getAttachmentKv().put(Constants.SERVER_EXEC_COST_KEY, 6010L); - - long beforeEncodeTime = System.currentTimeMillis(); - response.getAttachmentKv().put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeTime); - response.getAttachmentKv().put(Constants.SERVER_RECEIVE_REQ_TIME_KEY, beforeEncodeTime + 10); - response.getAttachmentKv().put(Constants.TRACE_ID_KEY, "123456789"); - - response.getNoneAdditionKv().put(Constants.RECEIVE_BYTE_MSG_TIME_KEY, beforeEncodeTime + 6010 + 10); - response.getNoneAdditionKv().put(Constants.DECODE_HEADER_COST, 1L); - response.getNoneAdditionKv().put(Constants.DECODE_BODY_COST, 1L); - response.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, "localhost:9090"); - - LogUtils.timeoutReqAdditionalLog(response); - } - - @Test - public void messageDelayTimeout() { - Response response = new RpcResponse(); - response.getAttachmentKv().put(Constants.REQUEST_TIMEOUT_KEY, 5000); - response.getAttachmentKv().put(Constants.EXECUTE_METHOD_COST, 600L); - response.getAttachmentKv().put(Constants.SERVER_EXEC_COST_KEY, 610L); - - long beforeEncodeTime = System.currentTimeMillis(); - response.getAttachmentKv().put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeTime); - response.getAttachmentKv().put(Constants.SERVER_RECEIVE_REQ_TIME_KEY, beforeEncodeTime + 3000); - response.getAttachmentKv().put(Constants.TRACE_ID_KEY, "123456789"); - - response.getNoneAdditionKv().put(Constants.RECEIVE_BYTE_MSG_TIME_KEY, beforeEncodeTime + 610 + 3000); - response.getNoneAdditionKv().put(Constants.DECODE_HEADER_COST, 1L); - response.getNoneAdditionKv().put(Constants.DECODE_BODY_COST, 1L); - response.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, "localhost:9090"); - - LogUtils.timeoutReqAdditionalLog(response); - } - - @Test - public void unknownTimeout() { - Response response = new RpcResponse(); - response.getAttachmentKv().put(Constants.REQUEST_TIMEOUT_KEY, 5000); - response.getAttachmentKv().put(Constants.EXECUTE_METHOD_COST, 600L); - response.getAttachmentKv().put(Constants.SERVER_EXEC_COST_KEY, 610L); - - long beforeEncodeTime = System.currentTimeMillis(); - response.getAttachmentKv().put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeTime); - response.getAttachmentKv().put(Constants.SERVER_RECEIVE_REQ_TIME_KEY, beforeEncodeTime + 500); - response.getAttachmentKv().put(Constants.TRACE_ID_KEY, "123456789"); - - response.getNoneAdditionKv().put(Constants.RECEIVE_BYTE_MSG_TIME_KEY, beforeEncodeTime + 610 + 500); - response.getNoneAdditionKv().put(Constants.DECODE_HEADER_COST, 1L); - response.getNoneAdditionKv().put(Constants.DECODE_BODY_COST, 1L); - response.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, "localhost:9090"); - - LogUtils.timeoutReqAdditionalLog(response); - } - - @Test - public void additionalNull() { - Response response = new RpcResponse(); - LogUtils.timeoutReqAdditionalLog(response); // unknow reason - } - -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/NetUriUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/NetUriUtilsTest.java deleted file mode 100644 index a860478d..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/NetUriUtilsTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import com.baidu.cloud.starlight.api.common.Constants; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.contrib.java.lang.system.EnvironmentVariables; - -/** - * Created by liuruisen on 2020/3/19. - */ -public class NetUriUtilsTest { - - @Rule - public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); - - @Test - public void parseQueryString() { - Map hashMap = NetUriUtils.parseQueryString(""); - Assert.assertTrue(hashMap.size() == 0); - - Map hashMap2 = NetUriUtils.parseQueryString("name=123&key=456"); - Assert.assertTrue(hashMap2.get("name").equals("123")); - - Map hashMap3 = NetUriUtils.parseQueryString("name=123&key=456&@@&key2=123"); - Assert.assertTrue(hashMap3.get("key2").equals("123")); - - } - - @Test - public void toQueryString() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - map.put("key2", "value2"); - Assert.assertEquals(NetUriUtils.toQueryString(map), "key1=value1&key2=value2"); - - Map map2 = new HashMap<>(); - Assert.assertEquals(NetUriUtils.toQueryString(map2), ""); - - Assert.assertEquals(NetUriUtils.toQueryString(null), ""); - } - - @Test - public void getIpByHost() { - - System.out.println(NetUriUtils.getIpByHost("localhost")); - Assert.assertEquals(NetUriUtils.getIpByHost("localhost"), "127.0.0.1"); - - Assert.assertEquals(NetUriUtils.getIpByHost("fghjk"), "fghjk"); - } - - @Test - public void getLocalHost() { - Assert.assertEquals(NetUriUtils.getLocalHost(), NetUriUtils.getLocalHost()); - } - - @Test - public void isValidAddress() { - Assert.assertFalse(NetUriUtils.isValidAddress(null)); - } - - @Test - public void getLocalHost2() { - clearLocalHostCache(); - environmentVariables.set(Constants.EM_APP, "em-name"); - environmentVariables.set(Constants.EM_PLATFORM, "em-platform"); - environmentVariables.set(Constants.EM_PRODUCT_LINE, "em-product"); - - environmentVariables.set(Constants.MATRIX_HOST_IP, "127.1.1.1"); - - Assert.assertEquals("127.1.1.1", NetUriUtils.getLocalHost()); - - clearLocalHostCache(); - environmentVariables.set(Constants.EM_IP, "127.1.1.2"); - Assert.assertEquals("127.1.1.2", NetUriUtils.getLocalHost()); - } - - @Test - public void getLocalHost3() { - environmentVariables.clear(Constants.EM_APP, Constants.MATRIX_HOST_IP); - String localhostIp = NetUriUtils.getLocalHost(); - System.out.println(localhostIp); - } - - private void clearLocalHostCache() { - try { - Class clazz = NetUriUtils.class; - Field field = clazz.getDeclaredField("localHostIp"); - field.setAccessible(true); - field.set(null, ""); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/StringUtilsTest.java b/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/StringUtilsTest.java deleted file mode 100644 index c3809255..00000000 --- a/starlight/starlight-api/src/test/java/com/baidu/cloud/starlight/api/utils/StringUtilsTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.api.utils; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/19. - */ -public class StringUtilsTest { - - @Test - public void parseInteger() { - - Integer result1 = StringUtils.parseInteger("123"); - Assert.assertTrue(result1 == 123); - - Integer result2 = StringUtils.parseInteger(""); - Assert.assertTrue(result2 == 0); - } - - @Test - public void isInteger() { - Assert.assertTrue(StringUtils.isInteger("123")); - Assert.assertFalse(StringUtils.isInteger("")); - Assert.assertFalse(StringUtils.isInteger(null)); - } - - @Test - public void isDigits() { - Assert.assertTrue(StringUtils.isDigits("123123213")); - Assert.assertFalse(StringUtils.isDigits(null)); - Assert.assertFalse(StringUtils.isDigits("")); - Assert.assertFalse(StringUtils.isDigits("2e12312312dsada")); - } - - @Test - public void isEquals() { - Assert.assertTrue(StringUtils.isEquals("123", "123")); - Assert.assertFalse(StringUtils.isEquals(null, "123")); - Assert.assertFalse(StringUtils.isEquals("123", null)); - Assert.assertTrue(StringUtils.isEquals(null, null)); - Assert.assertFalse(StringUtils.isEquals("23", "123213")); - } - - @Test - public void hasLength() { - Assert.assertTrue(StringUtils.hasLength("123")); - Assert.assertTrue(StringUtils.hasLength(" ")); - Assert.assertFalse(StringUtils.hasLength("")); - Assert.assertFalse(StringUtils.hasLength(null)); - } - - @Test - public void hasText() { - Assert.assertFalse(StringUtils.hasText(null)); - Assert.assertFalse(StringUtils.hasText("")); - Assert.assertFalse(StringUtils.hasText(" ")); - Assert.assertTrue(StringUtils.hasText("12345")); - } - - @Test - public void isNumeric() { - Assert.assertFalse(StringUtils.isNumeric(null)); - Assert.assertTrue(StringUtils.isNumeric("")); - Assert.assertFalse(StringUtils.isNumeric(" ")); - Assert.assertTrue(StringUtils.isNumeric("123")); - Assert.assertFalse(StringUtils.isNumeric("12 3")); - Assert.assertFalse(StringUtils.isNumeric("ab2c")); - Assert.assertFalse(StringUtils.isNumeric("12-3")); - Assert.assertFalse(StringUtils.isNumeric("12.3")); - } - - @Test - public void isEmpty() { - Assert.assertTrue(StringUtils.isEmpty(null)); - Assert.assertTrue(StringUtils.isEmpty("")); - Assert.assertFalse(StringUtils.isEmpty(" ")); - Assert.assertFalse(StringUtils.isEmpty("123n ")); - } - - @Test - public void substringAfterLast() { - String origin = "123213,,,,346"; - String compare = "346"; - String result = StringUtils.substringAfterLast(origin, ","); - Assert.assertTrue(result.equals(compare)); - - String result2 = StringUtils.substringAfterLast("", ","); - Assert.assertTrue(result2.equals("")); - - String result3 = StringUtils.substringAfterLast(origin, ""); - Assert.assertTrue(result3.equals("")); - } - - @Test - public void substringBeforeLast() { - String origin = "123213,,,,346"; - String compare = "123213,,,"; - String result = StringUtils.substringBeforeLast(origin, ","); - Assert.assertTrue(result.equals(compare)); - - String result2 = StringUtils.substringBeforeLast("", ","); - Assert.assertTrue(result2.equals("")); - - String result3 = StringUtils.substringBeforeLast(origin, ""); - Assert.assertTrue(result3.equals(origin)); - - String result4 = StringUtils.substringBeforeLast(null, ","); - Assert.assertTrue(result4 == null); - - String result5 = StringUtils.substringBeforeLast(origin, null); - Assert.assertTrue(result5.equals(origin)); - - String result6 = StringUtils.substringBeforeLast(origin, "."); - Assert.assertTrue(result6.equals(origin)); - } - - @Test - public void substringBetween() { - String origin = "123213,,,,346"; - String compare = "3213,,,,3"; - String result = StringUtils.substringBetween(origin, "12", "46"); - Assert.assertTrue(result.equals(compare)); - - String result2 = StringUtils.substringBetween("", ",", null); - Assert.assertTrue(result2 == null); - - String result3 = StringUtils.substringBetween(origin, "12", "2sadasd"); - Assert.assertTrue(result3 == null); - } - - @Test - public void trimAllWhitespace() { - String origin = "1 2 3 \n 4 \t 5"; - String result = StringUtils.trimAllWhitespace(origin); - Assert.assertTrue(result.equals("12345")); - - String result2 = StringUtils.trimAllWhitespace(""); - Assert.assertTrue(result2.equals("")); - } - - @Test - public void isBlank() { - Assert.assertTrue(StringUtils.isBlank(null)); - Assert.assertTrue(StringUtils.isBlank("")); - Assert.assertTrue(StringUtils.isBlank(" ")); - Assert.assertFalse(StringUtils.isBlank("bob")); - Assert.assertFalse(StringUtils.isBlank(" bob ")); - } - - @Test - public void trimToEmpty() { - Assert.assertEquals(StringUtils.trimToEmpty(null), ""); - Assert.assertEquals(StringUtils.trimToEmpty(""), ""); - Assert.assertEquals(StringUtils.trimToEmpty(" "), ""); - Assert.assertEquals(StringUtils.trimToEmpty("abc"), "abc"); - Assert.assertEquals(StringUtils.trimToEmpty(" abc "), "abc"); - } - - @Test - public void substringBefore() { - Assert.assertEquals(StringUtils.substringBefore(null, "."), null); - Assert.assertEquals(StringUtils.substringBefore("", "."), ""); - Assert.assertEquals(StringUtils.substringBefore("abc", "a"), ""); - Assert.assertEquals(StringUtils.substringBefore("abcba", "b"), "a"); - Assert.assertEquals(StringUtils.substringBefore("abc", "c"), "ab"); - Assert.assertEquals(StringUtils.substringBefore("abc", "d"), "abc"); - Assert.assertEquals(StringUtils.substringBefore("abc", ""), ""); - Assert.assertEquals(StringUtils.substringBefore("abc", null), "abc"); - } - - @Test - public void substringAfter() { - Assert.assertEquals(StringUtils.substringAfter(null, "23"), null); - Assert.assertEquals(StringUtils.substringAfter("", "123"), ""); - Assert.assertEquals(StringUtils.substringAfter("23", null), ""); - Assert.assertEquals(StringUtils.substringAfter("abc", "a"), "bc"); - Assert.assertEquals(StringUtils.substringAfter("abcba", "b"), "cba"); - Assert.assertEquals(StringUtils.substringAfter("abc", "c"), ""); - Assert.assertEquals(StringUtils.substringAfter("abc", "d"), ""); - Assert.assertEquals(StringUtils.substringAfter("abc", ""), "abc"); - } - - @Test - public void equalsIgnoreCase() { - Assert.assertTrue(StringUtils.equalsIgnoreCase(null, null)); - Assert.assertFalse(StringUtils.equalsIgnoreCase(null, "abc")); - Assert.assertFalse(StringUtils.equalsIgnoreCase("abc", null)); - Assert.assertTrue(StringUtils.equalsIgnoreCase("abc", "abc")); - Assert.assertTrue(StringUtils.equalsIgnoreCase("abc", "ABC")); - Assert.assertFalse(StringUtils.equalsIgnoreCase("abc", "ABDC")); - } -} \ No newline at end of file diff --git a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.extension.Ext1 b/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.extension.Ext1 deleted file mode 100644 index 03d38cb2..00000000 --- a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.extension.Ext1 +++ /dev/null @@ -1,3 +0,0 @@ -com.baidu.cloud.starlight.api.extension.impl.Ext1Impl1 -com.baidu.cloud.starlight.api.extension.impl.Ext1Impl2 -xxx=com.baidu.cloud.starlight.api.extension.impl.Ext1Impl3 \ No newline at end of file diff --git a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.core.transport.protocol.Protocol b/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.core.transport.protocol.Protocol deleted file mode 100644 index 132e5a73..00000000 --- a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.core.transport.protocol.Protocol +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.core.transport.protocol.test.ATestProtocol \ No newline at end of file diff --git a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.filter.Filter b/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.filter.Filter deleted file mode 100644 index 23fc0c18..00000000 --- a/starlight/starlight-api/src/test/resources/META-INF/services/com.baidu.cloud.starlight.filter.Filter +++ /dev/null @@ -1,2 +0,0 @@ -TestFilter -TestSameFilter \ No newline at end of file diff --git a/starlight/starlight-core/pom.xml b/starlight/starlight-core/pom.xml deleted file mode 100644 index 36fe236e..00000000 --- a/starlight/starlight-core/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-core - - true - - - - com.baidu.cloud - starlight-transport - ${project.version} - - - - org.powermock - powermock-module-junit4 - test - - - - org.powermock - powermock-api-mockito2 - test - - - - - - - - - com.github.os72 - protoc-jar-maven-plugin - - - - org.codehaus.mojo - cobertura-maven-plugin - - - - - com/baidu/cloud/starlight/exception/*.class - com/baidu/cloud/starlight/extension/*.class - - com/baidu/cloud/starlight/transport/protocol/brpc/BaiduRpcProto*.class - com/baidu/cloud/starlight/transport/protocol/brpc/StreamingRpcProto*.class - com/baidu/cloud/starlight/transport/protocol/http/springrest/RequestTemplateArgsResolver.class - com/baidu/cloud/starlight/transport/protocol/http/springrest/RequestTemplateGenerator.class - com/baidu/cloud/starlight/transport/protocol/http/springrest/EncodedRequestTemplateArgsResolver.class - - - - xml - html - - - true - - - - - - - diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientContextFilter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientContextFilter.java deleted file mode 100644 index ceb1781a..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientContextFilter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.utils.IdUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * Pass the parameters set by Consumer through RpcContext to Provider. Store some other context information for other - * feature. Order = 1 Created by liuruisen on 2020/9/2. - */ -public class ClientContextFilter implements Filter { - - private static final Logger LOGGER = LoggerFactory.getLogger(ClientContextFilter.class); - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - - // set remote address for easier access - try { - if (invoker instanceof ClientInvoker) { - ClientInvoker clientInvoker = (ClientInvoker) invoker; - URI remoteUri = clientInvoker.getClientPeer().getUri(); - RpcContext.getContext().setRemoteAddress(remoteUri.getHost(), remoteUri.getPort()); - } - - // set sessionID for easier access - if (RpcContext.getContext().getSessionID() == null) { - RpcContext.getContext().setSessionID(IdUtils.genUUID()); - } - - // set requestID for easier access - if (RpcContext.getContext().getRequestID() == null) { - RpcContext.getContext().setRequestID(String.valueOf(request.getId())); - } - - // set rpc context values to request kv, will be passed to the provider - if (RpcContext.getContext().get().size() > 0) { - for (Map.Entry entry : RpcContext.getContext().get().entrySet()) { - // 兼容暴露springrest协议,http请求->stagate->server的场景(异常stackoverflowerror) - if (entry.getKey().equalsIgnoreCase(Constants.SERVLET_REQUEST_KEY) - || entry.getKey().equalsIgnoreCase(Constants.SERVLET_RESPONSE_KEY)) { - continue; - } - request.getAttachmentKv().putIfAbsent(entry.getKey(), entry.getValue()); - } - } - // 跨线程释放 - request.getNoneAdditionKv().put("rpc_context", RpcContext.getContext()); - LOGGER.debug("Client RpcContext values in thread {} is {}", Thread.currentThread().getName(), - RpcContext.getContext().get()); - } catch (Throwable e) { - LOGGER.warn("Set RpcContext to Request Attachment failed, {}", e.getMessage()); - } - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - // TODO 此处临时清理下rds_route_tag的内容, - // 解决非StarlightServer,再使用StarlightClient调用后端场景不清除路由标识导致路由不符合预期, - // 如请求以Http方式进入HttpServer,HttpServer中在以Stalright方式调用后端,当前HttpServer的调用线程中Context将会一直存有 - // TODO 后续可从拆分RpcContext为client side和server side 根解 - Object contextObj = request.getNoneAdditionKv().get("rpc_context"); - if (contextObj instanceof RpcContext) { - RpcContext rpcContext = (RpcContext) contextObj; - // 使用凤睛时会set,作为全链路传递的路由标识 - rpcContext.remove("rds_route_tag"); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilter.java deleted file mode 100644 index 6a590a9a..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatService; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.core.statistics.StarlightStatistics; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * Client Monitor Filter: used by eye probe agent SPI: clientmonitor Created by liuruisen on 2020/4/20. - */ -public class ClientMonitorFilter implements Filter { - - private static final Logger LOGGER = LoggerFactory.getLogger(ClientMonitorFilter.class); - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - try { - Map traceSpanId = LogUtils.parseTraceIdSpanId(request); - request.getAttachmentKv().put(Constants.TRACE_ID_KEY, traceSpanId.get(LogUtils.TCID)); - request.getAttachmentKv().put(Constants.SPAN_ID_KEY, traceSpanId.get(LogUtils.SPID)); - request.getAttachmentKv().put(Constants.X_B3_TRACE_ID, traceSpanId.get(LogUtils.TCID)); - request.getAttachmentKv().put(Constants.X_B3_SPAN_ID, traceSpanId.get(LogUtils.SPID)); - // 兼容stargate逻辑 - if (request.getAttachmentKv().get(Constants.STARGATE_SESSION_ID_KEY) == null) { - request.getAttachmentKv().put(Constants.STARGATE_SESSION_ID_KEY, traceSpanId.get(LogUtils.TCID)); - } - request.getAttachmentKv().computeIfAbsent(Constants.STARGATE_REQUEST_ID_KEY, - k -> String.valueOf(request.getId())); - - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_CLIENT_REQUEST_TIME_KEY, - System.currentTimeMillis()); - } catch (Throwable e) { - LOGGER.warn("ClientMonitorFilter filterRequest failed, cause by ", e); - } - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - try { - Object beforeRequestTime = request.getNoneAdditionKv().get(Constants.BEFORE_CLIENT_REQUEST_TIME_KEY); - if (!(beforeRequestTime instanceof Long)) { - LOGGER.warn("Exception occur when record reqlog, " - + "msg: BEFORE_CLIENT_REQUEST_TIME_KEY is null in request logkv"); - } else { - LogUtils.addLogTimeAttachment(request, Constants.CLIENT_REQUEST_COST, - System.currentTimeMillis() - ((Long) beforeRequestTime)); - LogUtils.recordRequestLog(request, response); - } - - // record statistics - recordStats(request, response); - } catch (Throwable ignore) { - LOGGER.warn("ClientMonitorFilter filterResponse failed, cause by ", ignore); - } - } - - // record stats - private void recordStats(Request request, Response response) { - if (HeartbeatService.HEART_BEAT_SERVICE_NAME.equals(request.getServiceName())) { - // 心跳检测接口不参与业务统计信息的记录 - return; - } - if (request.getRemoteURI() != null && StarlightStatsManager.getStats(request.getRemoteURI()) != null) { - LOGGER.debug("ClientMonitorFilter start record stats"); - long startTime = System.currentTimeMillis(); - StarlightStatistics statistics = StarlightStatsManager.getStats(request.getRemoteURI()); - statistics.record(request, response); - long recordStatsCost = System.currentTimeMillis() - startTime; - LOGGER.debug("ClientMonitorFilter record stats cost {}", recordStatsCost); - if (recordStatsCost > 3) { - LOGGER.info("ClientMonitorFilter record stats cost {}", recordStatsCost); - } - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/FilterChain.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/FilterChain.java deleted file mode 100644 index 0ed9a4ef..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/FilterChain.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.core.rpc.callback.FilterCallback; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.transport.ClientPeer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * FilterChain 责任链机制 Created by liuruisen on 2019/12/8. - */ -public final class FilterChain { - - /** - * Build ClientInvoker chain - * - * @param clientInvoker - * @param filterNames split by "," - * @return - */ - public static ClientInvoker buildClientChainInvoker(final ClientInvoker clientInvoker, final String filterNames) { - // SPI get Client Filters - List filters = getFilters(filterNames); - // build filter chain ClientInvoker - if (filters == null || filters.size() == 0) { - return clientInvoker; - } - ClientInvoker resultInvoker = clientInvoker; - Collections.reverse(filters); - for (Filter filter : filters) { - final ClientInvoker next = resultInvoker; - resultInvoker = new ClientInvoker() { - @Override - public ClientPeer getClientPeer() { - return clientInvoker.getClientPeer(); - } - - @Override - public ServiceConfig getServiceConfig() { - return clientInvoker.getServiceConfig(); - } - - @Override - public void invoke(Request request, RpcCallback callback) { - filter.filterRequest(next, request, new FilterCallback(callback, filter, request)); - } - - @Override - public void init() { - // do nothing - } - - @Override - public void destroy() { - clientInvoker.destroy(); - } - }; - } - return resultInvoker; - } - - /** - * Build ServerInvoker chain - * - * @param serverInvoker - * @param filterNames split by "," - * @return - */ - public static ServiceInvoker buildServerChainInvoker(final ServiceInvoker serverInvoker, final String filterNames) { - // SPI get Server Filters - List filters = getFilters(filterNames); - - // build filter chain ServerInvoker - if (filters == null || filters.size() == 0) { - return serverInvoker; - } - ServiceInvoker resultInvoker = serverInvoker; - Collections.reverse(filters); - for (Filter filter : filters) { - final ServiceInvoker next = resultInvoker; - resultInvoker = new ServiceInvoker() { - @Override - public RpcService getRpcService() { - return serverInvoker.getRpcService(); - } - - @Override - public void invoke(Request request, RpcCallback callback) { - filter.filterRequest(next, request, new FilterCallback(callback, filter, request)); - } - - @Override - public void init() { - // do nothing - } - - @Override - public void destroy() { - serverInvoker.destroy(); - } - }; - } - return resultInvoker; - } - - private static List getFilters(final String filterNames) { - if (StringUtils.isBlank(filterNames)) { - return null; - } - List filters = new ArrayList<>(); - String[] filterNameList = filterNames.split(Constants.FILTER_NAME_SPLIT_KEY); - for (String filterName : filterNameList) { - if (StringUtils.isBlank(filterName)) { - continue; - } - filters.add(ExtensionLoader.getInstance(Filter.class).getExtension(filterName.trim())); - } - return filters; - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/GenericFilter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/GenericFilter.java deleted file mode 100644 index 7ad5ad39..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/GenericFilter.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.core.rpc.RpcServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.core.utils.PojoJsonUtils; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -/** - * Only used in server side Compatible with stargate framework Created by liuruisen on 2020/4/7. - */ -public class GenericFilter implements Filter { - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - if (GenericUtil.isGenericCall(request) // method name contains $invoke - && request.getParams() != null && request.getParams().length == 2) { // methodName + Object[] - - GenericUtil.markGeneric(request); // mark request generic - - Object[] params = request.getParams(); - String methodName = ((String) params[0]).trim(); - request.setMethodName(methodName); // methodName - - Object[] args = (Object[]) params[1]; // real args - // get method - ServiceInvoker serviceInvoker = RpcServiceRegistry.getInstance().discover(request.getServiceName()); - if (serviceInvoker == null) { - callback.onError(new StarlightRpcException(StarlightRpcException.SERVICE_NOT_FOUND_EXCEPTION, - "Service {" + request.getServiceName() + "} not found in provider")); - return; - } - Method method = serviceInvoker.getRpcService().getMethod(methodName); - if (method == null) { - callback.onError(new StarlightRpcException(StarlightRpcException.METHOD_NOT_FOUND_EXCEPTION, - "The called method {" + request.getMethodName() + "} does not exist")); - return; - } - Type[] paramTypes = method.getGenericParameterTypes(); - - try { - args = PojoJsonUtils.realize(args, paramTypes); // realize params - } catch (Exception e) { - callback.onError(new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Generic request exception, convert generic args to real args failed, error: " + e.getMessage())); - return; - } - request.setParams(args); - } else { - RpcContext.getContext().remove(Constants.IS_GENERIC_KEY); - if (request.getAttachmentKv() != null) { // not to be a generalization request, remove is_generic attach - request.getAttachmentKv().remove(Constants.IS_GENERIC_KEY); - } - } - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - try { - if (request.getAttachmentKv() != null && request.getAttachmentKv().get(Constants.IS_GENERIC_KEY) != null - && (Boolean) request.getAttachmentKv().get(Constants.IS_GENERIC_KEY)) { - - GenericUtil.markGeneric(response); - - Object result = response.getResult(); - response.setResult(PojoJsonUtils.generalize(result)); - } - } catch (Exception e) { - response.setResult(null); - response.setErrorMsg( - "Generic response exception, convert real result to generic result failed, error: " + e.getMessage()); - response.setStatus(StarlightRpcException.INTERNAL_SERVER_ERROR); - } - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerContextFilter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerContextFilter.java deleted file mode 100644 index 21868741..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerContextFilter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol.X_STARLIGHT_ID; - -/** - * Created by liuruisen on 2020/9/2. - */ -public class ServerContextFilter implements Filter { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServerContextFilter.class); - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - try { - Object remoteHost = request.getAttachmentKv().remove(RpcContext.REMOTE_HOST_KEY); - Object remotePort = request.getAttachmentKv().remove(RpcContext.REMOTE_PORT_KEY); - RpcContext.getContext().setRemoteAddress(remoteHost instanceof String ? (String) remoteHost : null, - remotePort instanceof Integer ? (Integer) remotePort : 0); - - RpcContext.getContext().set(request.getAttachmentKv()); - - // original stargate will set params types and params to request attachment, - // but is not used, we remove it to prevent encode/decode error - if (RpcContext.getContext().get(RpcContext.PARMTYPES_KEY) != null) { - RpcContext.getContext().remove(RpcContext.PARMTYPES_KEY); - } - if (RpcContext.getContext().get(RpcContext.PARMS_KEY) != null) { - RpcContext.getContext().remove(RpcContext.PARMS_KEY); - } - if (RpcContext.getContext().get(RpcContext.METHODNAME_KEY) != null) { - RpcContext.getContext().remove(RpcContext.METHODNAME_KEY); - } - // 删除生命周期为请求级别的Key,防止向下传递出现混乱 - RpcContext.getContext().remove(Constants.CONSUMER_APP_NAME_KEY); - RpcContext.getContext().remove(Constants.PROVIDER_APP_NAME_KEY); - RpcContext.getContext().remove(Constants.SERIALIZER_MODE_KEY); - RpcContext.getContext().remove(Constants.REQUEST_TIMEOUT_KEY); - RpcContext.getContext().remove(Constants.BEFORE_ENCODE_HEADER_TIME_KEY); - RpcContext.getContext().remove(X_STARLIGHT_ID); - LOGGER.debug("Server RpcContext values in thread {} is {}", Thread.currentThread().getName(), - RpcContext.getContext().get()); - } catch (Throwable e) { - LOGGER.warn("Set Request Attachment to RpcContext failed, {}", e.getMessage()); - } - - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - RpcContext.removeContext(); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerMonitorFilter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerMonitorFilter.java deleted file mode 100644 index 1753c9f0..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/filter/ServerMonitorFilter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -/** - * Server Monitor Filter: used by eye probe agent SPI: servermonitor Created by liuruisen on 2020/4/20. - */ -public class ServerMonitorFilter implements Filter { - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - // do nothing - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ClientProcessor.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ClientProcessor.java deleted file mode 100644 index 28de9f5f..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ClientProcessor.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.core.utils.KeyOrderedExecutor; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Type; - -/** - * Client side processor Used to callback response Created by liuruisen on 2020/2/20. - */ -public class ClientProcessor implements Processor { - - private static final Logger LOGGER = LoggerFactory.getLogger(ClientProcessor.class); - - private ThreadPoolFactory threadPoolFactory; - - public ClientProcessor(ThreadPoolFactory threadPoolFactory) { - this.threadPoolFactory = threadPoolFactory; - } - - private KeyOrderedExecutor sseCallBackExecutor = new KeyOrderedExecutor("sse-callback"); - - @Override - public ServiceRegistry getRegistry() { - throw new StarlightRpcException("Client side is not supported ServiceRegistry currently"); - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - if (msgBase instanceof Request) { - // log and discard - LOGGER.error("Received Request message in server side, but is not supported currently"); - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Received Request message in server side, but is not supported currently"); - } - Response response = (Response) msgBase; - - ClientProcessTask processTask = new ClientProcessTask(response, context); - LogUtils.addLogTimeAttachment(msgBase, Constants.BEFORE_THREAD_EXECUTE_TIME_KEY, System.currentTimeMillis()); - if (SpringRestSseProtocol.PROTOCOL_NAME.equals(response.getProtocolName())) { - sseCallBackExecutor.execute(response.getId(), processTask); - } else { - threadPoolFactory.getThreadPool().execute(processTask); - } - } - - @Override - public void close() { - if (threadPoolFactory != null) { - threadPoolFactory.close(); - } - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - this.threadPoolFactory = threadPoolFactory; - } - - @Override - public Integer waitTaskCount(String serviceKey) { - return threadPoolFactory.getThreadPool().getQueue().size(); - } - - @Override - public Integer processingCount(String serviceKey) { - return threadPoolFactory.getThreadPool().getActiveCount(); - } - - @Override - public Long completeCount(String serviceKey) { - return threadPoolFactory.getThreadPool().getCompletedTaskCount(); - } - - private class ClientProcessTask implements Runnable { - - private Response response; - - private RpcChannel context; - - public ClientProcessTask(Response response, RpcChannel context) { - this.response = response; - this.context = context; - } - - @Override - public void run() { - // set currentThread's contextClassLoader to requestThread's ClassLoader - // this make Protostuff get the correct Schema bound with ClassLoader - ClassLoader classLoader = LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY) - .get(context.channel().id().asLongText()); - if (classLoader != null) { - Thread.currentThread().setContextClassLoader(classLoader); - } else { - LOGGER.error("Class Loader related to channel {} is null, plz check", - context.channel().id().asLongText()); - } - - Object beforeThreadExeTime = response.getNoneAdditionKv().get(Constants.BEFORE_THREAD_EXECUTE_TIME_KEY); - if (beforeThreadExeTime instanceof Long) { - LogUtils.addLogTimeAttachment(response, Constants.WAIT_FOR_THREAD_COST, - System.currentTimeMillis() - ((Long) beforeThreadExeTime)); - } - - RpcCallback rpcCallback = context.removeCallback(response.getId()); - - if (SpringRestSseProtocol.PROTOCOL_NAME.equals(response.getProtocolName())) { - rpcCallback = (RpcCallback) context.getAttribute(Constants.SSE_CALLBACK_ATTR_KEY); - } - - if (rpcCallback == null) { - LogUtils.timeoutReqAdditionalLog(response); - // FIXME rpcCallback为null是会不会存在别的需要额外处理的情况 - return; - } - - response.setRequest(rpcCallback.getRequest()); - // response body decode - Class returnType = rpcCallback.getRequest().getReturnType(); - if (returnType == null) { - rpcCallback.onError(new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The returnType in the request message is empty. Cannot deserialize the response data!")); - return; - } - response.setReturnType(returnType); - Type genericType = rpcCallback.getRequest().getGenericReturnType(); - if (genericType == null) { - rpcCallback.onError(new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The genericReturnType in the request message is empty. " - + "Cannot deserialize the response data!")); - return; - } - response.setGenericReturnType(genericType); - // generic response - if (GenericUtil.isGenericCall(rpcCallback.getRequest())) { - GenericUtil.markGeneric(response); - } - // body decode in work thread - try { - if (response.getStatus() == Constants.SUCCESS_CODE.intValue() && response.getBodyBytes() != null - && response.getBodyBytes().length > 0) { - Protocol protocol = - ExtensionLoader.getInstance(Protocol.class).getExtension(response.getProtocolName()); - if (protocol == null) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The response's protocol information is not found, protocol {" + response.getProtocolName() - + "}"); - } - long beforeDecodeBodyTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_DECODE_BODY_TIME_KEY, - beforeDecodeBodyTime); - protocol.getDecoder().decodeBody(response); - LogUtils.addLogTimeAttachment(response, Constants.DECODE_BODY_COST, - System.currentTimeMillis() - beforeDecodeBodyTime); - } - } catch (Exception e) { - if (e instanceof CodecException) { - CodecException codecException = (CodecException) e; - e = new CodecException(codecException.getCode(), - codecException.getMessage() + " " + Serializer.DESERIALIZE_ERROR_MSG); - } - rpcCallback.onError(e); - return; - } - // callback - rpcCallback.onResponse(response); - } - } - - @Override - public Integer allWaitTaskCount() { - // wait task and running but not complete task - return waitTaskCount(null) + threadPoolFactory.getThreadPool().getActiveCount(); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServer.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServer.java deleted file mode 100644 index 0c0c99ea..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServer.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatService; -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatServiceImpl; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.api.transport.TransportFactory; -import com.baidu.cloud.starlight.api.utils.EnvUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.core.filter.FilterChain; -import com.baidu.cloud.starlight.core.rpc.threadpool.RpcThreadPoolFactory; -import com.baidu.cloud.starlight.protocol.http.springrest.SpringRestHandlerMapping; -import com.baidu.cloud.starlight.transport.StarlightTransportFactory; -import com.baidu.cloud.starlight.transport.netty.NettyServer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ThreadFactory; - -/** - * Created by liuruisen on 2020/1/13. - */ -public class DefaultStarlightServer implements StarlightServer { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultStarlightServer.class); - - private ServerPeer serverPeer; - - private URI uri; - - private String protocol; - - private String host; - - private Integer port; - - private TransportConfig transportConfig; - - private ThreadFactory threadFactory; - - public DefaultStarlightServer(String protocol, String host, Integer port, TransportConfig transportConfig, - ThreadFactory threadFactory) { - this.protocol = protocol; - this.host = host; - this.port = port; - this.transportConfig = transportConfig; - this.threadFactory = threadFactory; - } - - public DefaultStarlightServer(String protocol, String host, Integer port, TransportConfig transportConfig) { - this(protocol, host, port, transportConfig, null); - } - - public DefaultStarlightServer(String host, Integer port, TransportConfig transportConfig) { - this(null, host, port, transportConfig); - } - - /** - * 构造函数中的初始化逻辑移到 init() 方法 - */ - @Override - public void init() { - if (StringUtils.isBlank(protocol)) { - this.uri = assembleUri(null, host, port, transportConfig); - } else { - this.uri = assembleUri(protocol, host, port, transportConfig); - } - TransportFactory transportFactory = new StarlightTransportFactory(); - this.serverPeer = transportFactory.server(uri); - - if (threadFactory != null) { - ((NettyServer) this.serverPeer).setThreadFactory(threadFactory); - } - // <1> Processor - int maxBizWorkerNum = - uri.getParameter(Constants.MAX_BIZ_WORKER_NUM_KEY, Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE); - Processor processor = new ServerProcessor(RpcServiceRegistry.getInstance(), - new RpcThreadPoolFactory(Constants.DEFAULT_BIZ_THREAD_POOL_SIZE, maxBizWorkerNum, "s")); // s:server - // <3> init ServerPeer - serverPeer.init(); - serverPeer.setProcessor(processor); - // export heartbeat service - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setFilters("servermonitor"); // traceID and log record - export(HeartbeatService.class, new HeartbeatServiceImpl(), serviceConfig); - } - - /** - * CRaC Restore 场景重启 Server 少了 export HeartbeatService 部分逻辑: export HeartbeatService 管理本地数据结构,之前讨论过,Checkpoint 和 - * Restore 时对本地数据结构不做干预 - */ - public void restart() { - if (StringUtils.isBlank(protocol)) { - this.uri = assembleUri(null, host, this.port, transportConfig); - } else { - this.uri = assembleUri(protocol, host, this.port, transportConfig); - } - TransportFactory transportFactory = new StarlightTransportFactory(); - this.serverPeer = transportFactory.server(uri); - - if (threadFactory != null) { - ((NettyServer) this.serverPeer).setThreadFactory(threadFactory); - } - // <1> Processor - int maxBizWorkerNum = - uri.getParameter(Constants.MAX_BIZ_WORKER_NUM_KEY, Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE); - Processor processor = new ServerProcessor(RpcServiceRegistry.getInstance(), - new RpcThreadPoolFactory(Constants.DEFAULT_BIZ_THREAD_POOL_SIZE, maxBizWorkerNum, "s")); // s:server - // <3> init ServerPeer - serverPeer.init(); - serverPeer.setProcessor(processor); - } - - @Override - public void destroy() { - boolean gracefullyShutdown = - uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_ENABLE_KEY, Constants.GRACEFULLY_SHUTDOWN_ENABLE); - - // close serverPeer - if (serverPeer != null) { - if (gracefullyShutdown) { - int quietPeriod = uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_KEY, - Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_VALUE); - int timeout = uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_KEY, - Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_VALUE); - serverPeer.gracefullyShutdown(quietPeriod, timeout); - } else { - serverPeer.close(); - } - } - } - - @Override - public void serve() { - serverPeer.bind(); - } - - @Override - public void export(Class rpcInterface, Object rpcObject) { - // Init RpcService by rpcInterface and rpcObject - RpcService rpcService = new RpcService(rpcInterface, rpcObject); - // export rpcService - export(rpcService); - } - - @Override - public void export(Class rpcInterface, Object rpcObject, ServiceConfig serviceConfig) { - // Init RpcService by rpcInterface and rpcObject - RpcService rpcService = new RpcService(rpcInterface, rpcObject, serviceConfig); - // export rpcService - export(rpcService); - } - - @Override - public void export(RpcService rpcService) { - // Register {@link RpcService} to {@link ServiceRegistry} - ServiceRegistry serviceRegistry = RpcServiceRegistry.getInstance(); - // <2> init ServerInvoker - String filterNames = Constants.DEFAULT_SERVER_FILTERS; - ServiceConfig serviceConfig = rpcService.getServiceConfig(); - if (serviceConfig != null) { - filterNames = serviceConfig.getFilters() == null ? filterNames : serviceConfig.getFilters(); - } - ServiceInvoker serviceInvoker = - FilterChain.buildServerChainInvoker(new RpcServiceInvoker(rpcService), filterNames); - serviceRegistry.register(serviceInvoker); - - // create request mapping info, when service is spring rest type - SpringRestHandlerMapping handlerMapping = SpringRestHandlerMapping.getInstance(); - handlerMapping.createMapping(rpcService.getServiceClass(), rpcService.getServiceObject()); - - LOGGER.info("Export RpcService success, RpcService: {}", rpcService); - } - - @Override - public void unexport(Class rpcInterface) { - ServiceRegistry serviceRegistry = RpcServiceRegistry.getInstance(); - ServiceInvoker serviceInvoker = serviceRegistry.discover(rpcInterface.getName()); - if (serviceInvoker == null) { - return; - } - unexport(serviceInvoker.getRpcService()); - } - - @Override - public void unexport(RpcService rpcService) { - ServiceRegistry serviceRegistry = RpcServiceRegistry.getInstance(); - serviceRegistry.unRegister(serviceRegistry.discover(rpcService.getServiceName())); - } - - private URI assembleUri(String protocol, String host, Integer port, TransportConfig config) { - if (StringUtils.isBlank(host)) { - host = Constants.ANYHOST_VALUE; - } - URI.Builder uriBuilder = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, host, port); - if (!StringUtils.isBlank(protocol)) { - uriBuilder = new URI.Builder(protocol, host, port); - } - uriBuilder.param(Constants.CONNECT_TIMEOUT_KEY, config.getConnectTimeoutMills() == null - ? Constants.CONNECT_TIMEOUT_VALUE : config.getConnectTimeoutMills()); - uriBuilder.param(Constants.WRITE_TIMEOUT_KEY, - config.getWriteTimeoutMills() == null ? Constants.WRITE_TIMEOUT_VALUE : config.getWriteTimeoutMills()); - uriBuilder.param(Constants.ALL_IDLE_TIMEOUT_KEY, - config.getAllIdleTimeout() == null ? Constants.ALL_IDLE_TIMEOUT_VALUE : config.getAllIdleTimeout()); - uriBuilder.param(Constants.IO_THREADS_KEY, - config.getIoThreadNum() == null ? Constants.DEFAULT_IO_THREADS_VALUE : config.getIoThreadNum()); - uriBuilder.param(Constants.ACCEPT_THREADS_KEY, config.getAcceptThreadNum() == null - ? Constants.DEFAULT_ACCEPTOR_THREAD_VALUE : config.getAcceptThreadNum()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_ENABLE_KEY, config.getGracefullyShutdown() == null - ? Constants.GRACEFULLY_SHUTDOWN_ENABLE : config.getGracefullyShutdown()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_KEY, config.getGracefullyQuietPeriod() == null - ? Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_VALUE : config.getGracefullyQuietPeriod()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_KEY, config.getGracefullyTimeout() == null - ? Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_VALUE : config.getGracefullyTimeout()); - uriBuilder.param(Constants.CONNECT_KEEPALIVE_ENABLED_KEY, config.getConnectKeepAliveEnable() == null - ? Constants.CONNECT_KEEPALIVE_ENABLED_VALUE : config.getConnectKeepAliveEnable()); - uriBuilder.param(Constants.MAX_BIZ_WORKER_NUM_KEY, - config.getBizWorkThreadNum() == null ? maxBizThreadNum() : config.getBizWorkThreadNum()); - uriBuilder.param(Constants.NETTY_IO_RATIO_KEY, - config.getIoRatio() == null ? Constants.DEFAULT_NETTY_IO_RATIO : config.getIoRatio()); - return uriBuilder.build(); - } - - private int maxBizThreadNum() { - int maxBizWorkerNum = EnvUtils.getContainerThreadNum(Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE); - return maxBizWorkerNum; - } - - public void setPort(Integer port) { - this.port = port; - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvoker.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvoker.java deleted file mode 100644 index fef42c9a..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvoker.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.utils.IDGenerator; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.protocol.stargate.StargateProtocol; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Client Invoker Used to serialize body and request with {@link ClientPeer} Created by liuruisen on 2020/2/14. - */ -public class RpcClientInvoker implements ClientInvoker { - - private static final Logger LOGGER = LoggerFactory.getLogger(RpcClientInvoker.class); - - private final ClientPeer clientPeer; - - private final ServiceConfig serviceConfig; - - public RpcClientInvoker(ClientPeer clientPeer, ServiceConfig serviceConfig) { - this.clientPeer = clientPeer; - this.serviceConfig = serviceConfig; - } - - @Override - public ClientPeer getClientPeer() { - return clientPeer; - } - - @Override - public ServiceConfig getServiceConfig() { - return serviceConfig; - } - - @Override - public void invoke(Request request, RpcCallback callback) { - String protocolName = request.getProtocolName(); - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName); - // 当请求协议为stargate时,生成更具唯一性的ID - changeIdForStargate(request); - // body encode: Construct and Serialize - try { - long beforeTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_ENCODE_BODY_TIME_KEY, beforeTime); - protocol.getEncoder().encodeBody(request); - LogUtils.addLogTimeAttachment(request, Constants.ENCODE_BODY_COST, System.currentTimeMillis() - beforeTime); - } catch (CodecException e) { - callback.onError(e); - return; - } - - // request - try { - request.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, - clientPeer.getUri() != null ? clientPeer.getUri().getAddress() : null); - - request.getNoneAdditionKv().put(Constants.BEFORE_IO_THREAD_EXECUTE_TIME_KEY, System.currentTimeMillis()); - - // send msg - clientPeer.request(request, callback); - } catch (TransportException e) { - // call back error - callback.onError(e); - } - } - - @Override - public void destroy() { - // do nothing - } - - @Override - public void init() { - // do nothing - } - - private void changeIdForStargate(Request request) { - try { - String protocolName = request.getProtocolName(); - if (protocolName.equals(StargateProtocol.PROTOCOL_NAME)) { - request.setId(IDGenerator.getInstance().nextId()); - } - } catch (Throwable e) { - LOGGER.warn("Generate stargate requestId form IDGenerator failed, caused by ", e); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvoker.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvoker.java deleted file mode 100644 index 324ce554..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvoker.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Created by liuruisen on 2020/2/13. - */ -public class RpcServiceInvoker implements ServiceInvoker { - - private static final Logger LOGGER = LoggerFactory.getLogger(RpcServiceInvoker.class); - - private RpcService rpcService; - - public RpcServiceInvoker(RpcService rpcService) { - this.rpcService = rpcService; - } - - @Override - public RpcService getRpcService() { - return rpcService; - } - - @Override - public void invoke(Request request, RpcCallback callback) { - Object beforeServFilterExec = request.getNoneAdditionKv().get(Constants.BEFORE_SERVER_FILTER_EXEC_TIME_KEY); - if (beforeServFilterExec instanceof Long) { - LogUtils.addLogTimeAttachment(request, Constants.SERVER_FILTER_EXEC_COST_KEY, - System.currentTimeMillis() - ((Long) beforeServFilterExec)); - } - - // get target method - Method method = request.getMethod(); - if (method == null) { - method = rpcService.getMethod(request.getMethodName()); - if (method == null) { - callback.onError(new StarlightRpcException(StarlightRpcException.METHOD_NOT_FOUND_EXCEPTION, - "The called method {" + request.getMethodName() + "} does not exist")); - return; - } - } - - // get service obj - Object serviceObj = request.getServiceObj(); - if (serviceObj == null) { - serviceObj = rpcService.getServiceObject(); - } - - Response response = new RpcResponse(request.getId()); - response.setProtocolName(request.getProtocolName()); - response.setRequest(request); - - // execute - try { - long beforeMethodExeTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_EXECUTE_METHOD_TIME_KEY, beforeMethodExeTime); - Object result = method.invoke(serviceObj, request.getParams()); - LogUtils.addLogTimeAttachment(request, Constants.EXECUTE_METHOD_COST, - System.currentTimeMillis() - beforeMethodExeTime); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult(result); - response.setReturnType(method.getReturnType()); - response.setGenericReturnType(method.getGenericReturnType()); - - // init sseEmitter - if (result instanceof RpcSseEmitter) { - RpcSseEmitter rpcSseEmitter = (RpcSseEmitter) result; - rpcSseEmitter.init(callback); - } else { - callback.onResponse(response); - } - } catch (Throwable e) { - LOGGER.error("Failed to execute method " + request.getMethodName() + ", caused by ", e); - callback.onError(convertThrowable(e)); - } - } - - @Override - public void destroy() { - // do nothing - } - - @Override - public void init() { - // do nothing - } - - protected StarlightRpcException convertThrowable(Throwable throwable) { - StringBuilder errMsgSb = new StringBuilder("Server failed to execute target method"); - errMsgSb.append(", cause by: "); - - if (throwable instanceof InvocationTargetException && throwable.getCause() != null) { - errMsgSb.append(throwable.getCause().getClass().getSimpleName()); - } else { - errMsgSb.append(throwable.getClass().getSimpleName()); - } - - errMsgSb.append(", "); - - if (throwable.getCause() != null) { - errMsgSb - .append(throwable.getMessage() == null ? throwable.getCause().getMessage() : throwable.getMessage()); - } else { - errMsgSb.append(throwable.getMessage()); - } - - return new StarlightRpcException(StarlightRpcException.BIZ_ERROR, errMsgSb.toString()); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistry.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistry.java deleted file mode 100644 index 164c8394..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistry.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.exception.RpcException; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.utils.StringUtils; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Created by liuruisen on 2020/2/21. - */ -public class RpcServiceRegistry implements ServiceRegistry { - - private static RpcServiceRegistry serviceRegistry; - - private final Map rpcServiceMap; - - // store ServiceName and serviceClass mapping relationship, such serviceId <--> - // we can support brpc cross-language call by this way - private final Map serviceInterfaceMap; - - private RpcServiceRegistry() { - this.rpcServiceMap = new ConcurrentHashMap<>(); - this.serviceInterfaceMap = new ConcurrentHashMap<>(); - } - - public static RpcServiceRegistry getInstance() { - synchronized (RpcServiceRegistry.class) { - if (serviceRegistry == null) { - serviceRegistry = new RpcServiceRegistry(); - } - } - return serviceRegistry; - } - - @Override - public void register(ServiceInvoker serviceInvoker) { - // register service - String serviceClassName = serviceInvoker.getRpcService().getServiceClass().getName(); - if (rpcServiceMap.get(serviceClassName) != null) { - throw new RpcException("Service repeated register, serviceClass: " + serviceClassName); - } - rpcServiceMap.put(serviceClassName, serviceInvoker); - - // store serviceName and serviceClass relation map - String serviceKey = serviceInvoker.getRpcService().getServiceName(); - if (serviceInterfaceMap.get(serviceKey) != null) { - throw new RpcException("Service repeated register, serviceName: " + serviceKey); - } - serviceInterfaceMap.put(serviceKey, serviceClassName); - } - - @Override - public void unRegister(ServiceInvoker serviceInvoker) { - String serviceName = serviceInvoker.getRpcService().getServiceName(); - serviceInterfaceMap.remove(serviceName); - - String serviceClassName = serviceInvoker.getRpcService().getServiceClass().getName(); - rpcServiceMap.remove(serviceClassName); - } - - @Override - public ServiceInvoker discover(String serviceName) { - ServiceInvoker serviceInvoker = rpcServiceMap.get(serviceName); - if (serviceInvoker != null) { - return serviceInvoker; - } - // serviceId --> serviceClassName - String serviceClassName = serviceInterfaceMap.get(serviceName); - if (StringUtils.isEmpty(serviceClassName)) { - return null; - } - return rpcServiceMap.get(serviceClassName); - } - - @Override - public Set rpcServices() { - Set serviceInvokers = new HashSet<>(); - serviceInvokers.addAll(rpcServiceMap.values()); - return serviceInvokers; - } - - @Override - public void destroy() { - if (serviceInterfaceMap.size() > 0) { - serviceInterfaceMap.clear(); - } - - if (rpcServiceMap.size() > 0) { - rpcServiceMap.clear(); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ServerProcessor.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ServerProcessor.java deleted file mode 100644 index 4cc1d7fd..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/ServerProcessor.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.core.rpc.callback.InvokeCallBack; -import com.baidu.cloud.starlight.core.rpc.callback.SseServerCallBack; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; -import java.util.Objects; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Server side Processor Capable of invoke requests and return responses Created by liuruisen on 2020/2/10. - */ -public class ServerProcessor implements Processor { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServerProcessor.class); - - private ServiceRegistry serviceRegistry; - - private ThreadPoolFactory threadPoolFactory; - - public ServerProcessor(ServiceRegistry serviceRegistry, ThreadPoolFactory threadPoolFactory) { - this.serviceRegistry = serviceRegistry; - this.threadPoolFactory = threadPoolFactory; - } - - @Override - public ServiceRegistry getRegistry() { - return serviceRegistry; - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - if (msgBase instanceof Response) { - LOGGER.error("Received Response message in server side, but is not supported currently"); - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Received Response message in server side, but is not supported currently"); - } - - Request request = (Request) msgBase; - // construct callback - RpcCallback callback = Objects.equals(request.getProtocolName(), SpringRestSseProtocol.PROTOCOL_NAME) - ? new SseServerCallBack(request, context) : new InvokeCallBack(request, context); - - // service check - ServiceInvoker serviceInvoker = serviceRegistry.discover(request.getServiceName()); - if (serviceInvoker == null) { - callback.onError(new StarlightRpcException(StarlightRpcException.SERVICE_NOT_FOUND_EXCEPTION, - "Service {" + request.getServiceName() + "} not found in provider")); - return; - } - RpcService rpcService = serviceInvoker.getRpcService(); - if (rpcService.getServiceConfig() != null && rpcService.getServiceConfig().getInvokeTimeoutMills() != null) { - // add Timeout - Integer invokeTimeout = rpcService.getServiceConfig().getInvokeTimeoutMills(); - if (invokeTimeout != null && invokeTimeout > 0) { - Timeout timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - callback.onError(new StarlightRpcException(StarlightRpcException.TIME_OUT_EXCEPTION, - "Call service {" + request.getServiceName() + "} " + "method {" + request.getMethodName() - + "} time out")); - } - }, invokeTimeout, TimeUnit.MILLISECONDS); - - callback.addTimeout(timeout); - } - } - ServerProcessTask task = new ServerProcessTask(request, callback, serviceInvoker); - LogUtils.addLogTimeAttachment(msgBase, Constants.BEFORE_THREAD_EXECUTE_TIME_KEY, System.currentTimeMillis()); - threadPoolFactory.getThreadPool(rpcService).execute(task); - } - - @Override - public void close() { - if (threadPoolFactory != null) { - threadPoolFactory.close(); - } - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - this.threadPoolFactory = threadPoolFactory; - } - - @Override - public Integer waitTaskCount(String serviceKey) { - RpcService rpcService = serviceRegistry.discover(serviceKey).getRpcService(); - if (rpcService != null) { - return threadPoolFactory.getThreadPool(rpcService).getQueue().size(); - } - return null; // null: Data is invalid - } - - @Override - public Integer processingCount(String serviceKey) { - RpcService rpcService = serviceRegistry.discover(serviceKey).getRpcService(); - if (rpcService != null) { - return threadPoolFactory.getThreadPool(rpcService).getActiveCount(); - } - return null; // null: Data is invalid - } - - @Override - public Long completeCount(String serviceKey) { - RpcService rpcService = serviceRegistry.discover(serviceKey).getRpcService(); - if (rpcService != null) { - return threadPoolFactory.getThreadPool(rpcService).getCompletedTaskCount(); - } - return null; // null: Data is invalid - } - - @Override - public Integer allWaitTaskCount() { - ThreadPoolExecutor defaultThreadPool = threadPoolFactory.getThreadPool(); - Integer allWaitTaskCount = defaultThreadPool.getQueue().size() // wait task - + defaultThreadPool.getActiveCount(); // not complete task - - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - for (ServiceInvoker serviceInvoker : registry.rpcServices()) { - ThreadPoolExecutor serviceThreadPool = threadPoolFactory.getThreadPool(serviceInvoker.getRpcService()); - if (serviceThreadPool != defaultThreadPool) { - allWaitTaskCount = allWaitTaskCount + serviceThreadPool.getQueue().size() // wait task - + serviceThreadPool.getActiveCount(); // not complete task - } - } - - return allWaitTaskCount; - } - - private class ServerProcessTask implements Runnable { - - private Request request; - - private RpcCallback callback; - - private ServiceInvoker serviceInvoker; - - public ServerProcessTask(Request request, RpcCallback callback, ServiceInvoker serviceInvoker) { - this.request = request; - this.callback = callback; - this.serviceInvoker = serviceInvoker; - } - - @Override - public void run() { - Object beforeThreadExeTime = request.getNoneAdditionKv().get(Constants.BEFORE_THREAD_EXECUTE_TIME_KEY); - if (beforeThreadExeTime instanceof Long) { - LogUtils.addLogTimeAttachment(request, Constants.WAIT_FOR_THREAD_COST, - System.currentTimeMillis() - ((Long) beforeThreadExeTime)); - } - - // request body decode - RpcService rpcService = serviceInvoker.getRpcService(); - - if (!GenericUtil.isGenericCall(request)) { - Method method = rpcService.getMethod(request.getMethodName()); - if (method == null) { - callback.onError(new StarlightRpcException(StarlightRpcException.METHOD_NOT_FOUND_EXCEPTION, - "The called method {" + request.getMethodName() + "} does not exist")); - return; - } - Class[] paramTypes = method.getParameterTypes(); - request.setParamsTypes(paramTypes); // used to deserialize - request.setGenericParamsTypes(method.getGenericParameterTypes()); // used in springrest - request.setReturnType(method.getReturnType()); - } else { // generic request - GenericUtil.markGeneric(request); - } - - // body decode in work thread - try { - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(request.getProtocolName()); - if (protocol == null) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The request's protocol information is not found"); - } - long beforeTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_DECODE_BODY_TIME_KEY, beforeTime); - protocol.getDecoder().decodeBody(request); - LogUtils.addLogTimeAttachment(request, Constants.DECODE_BODY_COST, - System.currentTimeMillis() - beforeTime); - } catch (Exception e) { - if (e instanceof CodecException) { - CodecException codecException = (CodecException) e; - e = new CodecException(codecException.getCode(), - codecException.getMessage() + " " + Serializer.DESERIALIZE_ERROR_MSG); - } - callback.onError(e); - return; - } - // invoke - LogUtils.addLogTimeAttachment(request, Constants.BEFORE_SERVER_FILTER_EXEC_TIME_KEY, - System.currentTimeMillis()); - serviceInvoker.invoke(request, callback); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/SingleStarlightClient.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/SingleStarlightClient.java deleted file mode 100644 index 019929cc..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/SingleStarlightClient.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.heartbeat.HeartbeatService; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.TransportFactory; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.core.filter.FilterChain; -import com.baidu.cloud.starlight.core.rpc.threadpool.RpcThreadPoolFactory; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import com.baidu.cloud.starlight.protocol.brpc.BrpcProtocol; -import com.baidu.cloud.starlight.transport.netty.NettyClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Starlight Client associated with a single Server instance, facade of {@link ClientPeer} and {@link ClientInvoker} Can - * generate Invoker, execute request asynchronous - * - * Created by liuruisen on 2019/12/6. - */ -public class SingleStarlightClient implements StarlightClient { - private static final Logger LOGGER = LoggerFactory.getLogger(SingleStarlightClient.class); - - private final URI uri; - - // map of interfaceName and ClientInvoker - private final Map clientInvokers; - - private ClientPeer clientPeer; - - private AtomicBoolean isInitialed = new AtomicBoolean(false); - - private static volatile ThreadPoolFactory threadPoolOfAll; - - public SingleStarlightClient(String remoteIp, Integer remotePort, TransportConfig transportConfig, - ThreadFactory ioThreadFactory) { - this.clientInvokers = new ConcurrentHashMap<>(); - this.uri = assembleUri(remoteIp, remotePort, transportConfig); - TransportFactory transportFactory = - ExtensionLoader.getInstance(TransportFactory.class).getExtension(Constants.DEFAULT_TRANSPORT_FACTORY_NAME); - this.clientPeer = transportFactory.client(uri); - - if (ioThreadFactory != null && (clientPeer instanceof NettyClient)) { - ((NettyClient) clientPeer).setThreadFactory(ioThreadFactory); - } - - } - - public SingleStarlightClient(String remoteIp, Integer remotePort, TransportConfig transportConfig) { - this(remoteIp, remotePort, transportConfig, null); - } - - @Override - public URI remoteURI() { - return this.uri; - } - - @Override - public void init() { - if (threadPoolOfAll == null) { - synchronized (SingleStarlightClient.class) { - if (threadPoolOfAll == null) { - // max=500 - int maxWorkerNum = - uri.getParameter(Constants.MAX_BIZ_WORKER_NUM_KEY, Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE); - // c: client - threadPoolOfAll = - new RpcThreadPoolFactory(Constants.DEFAULT_BIZ_THREAD_POOL_SIZE, maxWorkerNum, "c"); - } - } - } - if (isInitialed.compareAndSet(false, true)) { - // Processor init - Processor processor = new ClientProcessor(threadPoolOfAll); - clientPeer.setProcessor(processor); - clientPeer.init(); - try { - long startTime = System.currentTimeMillis(); - clientPeer.connect(); - LOGGER.debug("Connect to remote cost: {}", System.currentTimeMillis() - startTime); - } catch (Exception e) { // will reconnect in request stage - LOGGER.warn("Connect to remote {} failed when init the single client, cause by {}", uri.getAddress(), - e.getMessage()); - } - // refer heartbeat service - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setFilters("clientmonitor"); // record heartbeat log - refer(HeartbeatService.class, serviceConfig); - updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - } - } - - @Override - public void refer(Class serviceClass, ServiceConfig serviceConfig) { - if (serviceClass.getInterfaces() != null && serviceClass.getInterfaces().length > 0) { - // async future interface or callback interface - if (serviceClass.getInterfaces().length > 1) { - throw new StarlightRpcException( - "Starlight not support Multiple inheritance, " + "Only supports one layer of inheritance"); - } - serviceClass = serviceClass.getInterfaces()[0]; - } - - String serviceName = serviceConfig.serviceName(serviceClass); - if (clientInvokers.get(serviceName) != null) { - return; - } - - // get filters - String filterNames = Constants.DEFAULT_CLIENT_FILTERS; - if (serviceConfig != null) { - filterNames = serviceConfig.getFilters() == null ? filterNames : serviceConfig.getFilters(); - } - - // Create Default ClientInvoker - ClientInvoker clientInvoker = - FilterChain.buildClientChainInvoker(new RpcClientInvoker(clientPeer, serviceConfig), filterNames); - clientInvokers.put(serviceName, clientInvoker); - } - - @Override - public void request(Request request, RpcCallback callback) { - - request.setRemoteURI(uri); - - if (!isActive() && !HeartbeatService.HEART_BEAT_SERVICE_NAME.equals(request.getServiceName())) { - LOGGER.warn("Receive request when Client is inactive, status {}, request {}, remoteAddress {}", - clientPeer.status(), request, uri.getHost() + ":" + uri.getPort()); - } - - // set protocol and serviceConfig - String protocolName = request.getProtocolName(); - if (StringUtils.isBlank(protocolName)) { - ServiceConfig serviceConfig = request.getServiceConfig(); - protocolName = serviceConfig.getProtocol(); - request.setProtocolName(protocolName); - } - - // check request - try { - checkRequest(request); - } catch (StarlightRpcException e) { - callback.onError(e); - return; - } - - try { - String serviceName = request.getServiceName(); - ClientInvoker clientInvoker = clientInvokers.get(serviceName); - clientInvoker.invoke(request, callback); - } catch (Exception e) { - LOGGER.error("Unhandled exception was caught when request, request {}:{}", request.getServiceName(), - request.getMethodName(), e); - callback.onError(new StarlightRpcException(StarlightRpcException.UNKNOW, - "Unhandled exception was caught when request, request " + request.getServiceName() + ":" - + request.getMethodName() + ", cause by " + e.getMessage())); - } - } - - private void checkRequest(Request request) throws StarlightRpcException { - - // check invoker - String serviceName = request.getServiceName(); - ClientInvoker clientInvoker = clientInvokers.get(serviceName); - if (clientInvoker == null) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The request service has not been refer, please call refer() before request, " + "service {" - + serviceName + "}"); - } - - // check protocol - String protocolName = request.getProtocolName(); - try { - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName); - if (protocol == null) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The protocol message in request is not support, protocolName {" + protocolName + "}"); - } - } catch (Exception e) { - if (e instanceof StarlightRpcException) { - throw e; - } - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "The protocol message in request is illegal, protocolName {" + protocolName + "}", e); - } - - try { - if (protocolName.equals(BrpcProtocol.PROTOCOL_NAME)) { - BrpcProtocol.checkRequest(request); - } - } catch (StarlightRpcException e) { - throw e; - } - } - - @Override - public void destroy() { - if (isInitialed.compareAndSet(true, false)) { - StarlightStatsManager.removeStats(remoteURI()); - boolean gracefullyShutdown = - uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_ENABLE_KEY, Constants.GRACEFULLY_SHUTDOWN_ENABLE); - if (clientPeer != null) { - if (gracefullyShutdown) { - int quietPeriod = uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_KEY, - Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_VALUE); - int timeout = uri.getParameter(Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_KEY, - Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_VALUE); - clientPeer.gracefullyShutdown(quietPeriod, timeout); - } else { - clientPeer.close(); - } - } - if (clientInvokers.size() > 0) { - clientInvokers.clear(); - } - } - } - - /** - * We use URI to store transport configuration - * - * @param ip - * @param port - * @param config - * @return - */ - private URI assembleUri(String ip, Integer port, TransportConfig config) { - URI.Builder uriBuilder = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, ip, port); - uriBuilder.param(Constants.CONNECT_TIMEOUT_KEY, config.getConnectTimeoutMills() == null - ? Constants.CONNECT_TIMEOUT_VALUE : config.getConnectTimeoutMills()); - uriBuilder.param(Constants.WRITE_TIMEOUT_KEY, - config.getWriteTimeoutMills() == null ? Constants.WRITE_TIMEOUT_VALUE : config.getWriteTimeoutMills()); - uriBuilder.param(Constants.REQUEST_TIMEOUT_KEY, config.getRequestTimeoutMills() == null - ? Constants.REQUEST_TIMEOUT_VALUE : config.getRequestTimeoutMills()); - uriBuilder.param(Constants.READ_IDLE_TIMEOUT_KEY, - config.getReadIdleTimeout() == null ? Constants.READ_IDLE_TIMEOUT_VALUE : config.getReadIdleTimeout()); - uriBuilder.param(Constants.IO_THREADS_KEY, - config.getIoThreadNum() == null ? Constants.DEFAULT_IO_THREADS_VALUE : config.getIoThreadNum()); - uriBuilder.param(Constants.MAX_HEARTBEAT_TIMES_KEY, config.getMaxHeartbeatTimes() == null - ? Constants.MAX_HEARTBEAT_TIMES_VALUE : config.getMaxHeartbeatTimes()); - uriBuilder.param(Constants.RPC_CHANNEL_TYPE_KEY, - config.getChannelType() == null ? Constants.DEFAULT_RPC_CHANNEL_TYPE_VALUE : config.getChannelType()); - uriBuilder.param(Constants.MAX_TOTAL_CONNECTIONS_KEY, - config.getMaxConnections() == null ? Constants.MAX_TOTAL_CONNECTIONS : config.getMaxConnections()); - uriBuilder.param(Constants.MAX_IDLE_CONNECTIONS_KEY, - config.getMaxIdleConnections() == null ? Constants.MAX_IDLE_CONNECTIONS : config.getMaxIdleConnections()); - uriBuilder.param(Constants.MIN_IDLE_CONNECTIONS_KEY, - config.getMinIdleConnections() == null ? Constants.MIN_IDLE_CONNECTIONS : config.getMinIdleConnections()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_ENABLE_KEY, config.getGracefullyShutdown() == null - ? Constants.GRACEFULLY_SHUTDOWN_ENABLE : config.getGracefullyShutdown()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_KEY, config.getGracefullyQuietPeriod() == null - ? Constants.GRACEFULLY_SHUTDOWN_QUIET_PERIOD_VALUE : config.getGracefullyQuietPeriod()); - uriBuilder.param(Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_KEY, config.getGracefullyTimeout() == null - ? Constants.GRACEFULLY_SHUTDOWN_TIMEOUT_VALUE : config.getGracefullyTimeout()); - uriBuilder.param(Constants.CONNECT_KEEPALIVE_ENABLED_KEY, config.getConnectKeepAliveEnable() == null - ? Constants.CONNECT_KEEPALIVE_ENABLED_VALUE : config.getConnectKeepAliveEnable()); - uriBuilder.param(Constants.MAX_BIZ_WORKER_NUM_KEY, config.getBizWorkThreadNum() == null - ? Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE : config.getBizWorkThreadNum()); - uriBuilder.param(Constants.NETTY_IO_RATIO_KEY, - config.getIoRatio() == null ? Constants.DEFAULT_NETTY_IO_RATIO : config.getIoRatio()); - - if (config.getAdditional() != null) { - uriBuilder.params(config.getAdditional()); - } - - return uriBuilder.build(); - } - - @Override - public boolean isActive() { - if (clientPeer == null) { - return false; - } - - if (clientPeer.status() == null) { - return false; - } - - return PeerStatus.Status.ACTIVE.equals(clientPeer.status().getStatus()); - } - - @Override - public PeerStatus getStatus() { - return this.clientPeer.status(); - } - - @Override - public void updateStatus(PeerStatus newStatus) { - this.clientPeer.updateStatus(newStatus); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BaseInvokeCallBack.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BaseInvokeCallBack.java deleted file mode 100644 index 38e4f354..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BaseInvokeCallBack.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.RpcException; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.thirdparty.netty.util.Timeout; - -/** - * Server端 服务调用callback 基础类 - */ -public class BaseInvokeCallBack implements RpcCallback { - - private Request request; - - private RpcChannel context; - - private Timeout timeout; - - public BaseInvokeCallBack(Request request, RpcChannel context) { - this.request = request; - this.context = context; - } - - @Override - public void onResponse(Response response) { - if (timeout != null && !timeout.isCancelled()) { - timeout.cancel(); - } - - response.setRequest(request); - // serialize result body - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(request.getProtocolName()); - - // encode body - long beforeTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_ENCODE_BODY_TIME_KEY, beforeTime); - protocol.getEncoder().encodeBody(response); - LogUtils.addLogTimeAttachment(response, Constants.ENCODE_BODY_COST, System.currentTimeMillis() - beforeTime); - - // send msg - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_IO_THREAD_EXECUTE_TIME_KEY, - System.currentTimeMillis()); - context.send(response); - } - - @Override - public void onError(Throwable e) { - - if (timeout != null && !timeout.isCancelled()) { - timeout.cancel(); - } - - Response response = new RpcResponse(request.getId()); - response.setProtocolName(request.getProtocolName()); - if (e instanceof RpcException) { - response.setStatus(((RpcException) e).getCode()); - } else { - response.setStatus(StarlightRpcException.INTERNAL_SERVER_ERROR); - } - response.setErrorMsg(e.getMessage()); - response.setRequest(request); // store as context - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(request.getProtocolName()); - - // encode body - long beforeTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_ENCODE_BODY_TIME_KEY, beforeTime); - protocol.getEncoder().encodeBody(response); - LogUtils.addLogTimeAttachment(response, Constants.ENCODE_BODY_COST, System.currentTimeMillis() - beforeTime); - - // send msg - LogUtils.addLogTimeAttachment(response, Constants.BEFORE_IO_THREAD_EXECUTE_TIME_KEY, - System.currentTimeMillis()); - context.send(response); - } - - @Override - public void addTimeout(Timeout timeout) { - this.timeout = timeout; - } - - @Override - public Request getRequest() { - return request; - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallback.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallback.java deleted file mode 100644 index 47c7d2d4..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallback.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.thirdparty.netty.util.Timeout; - -/** - * Wrap Biz Callback, Async Call: Callback mode 用户采用Callback的异步调用方式时使用此类(依据用户参数信息进行判断) 在StarlightClient request 前封装 - * Created by liuruisen on 2019/12/8. - */ -public class BizWrapCallback implements RpcCallback { - - private final Callback bizCallback; - - private final Request request; - - private Timeout timeout; - - public BizWrapCallback(Callback bizCallback, Request request) { - this.bizCallback = bizCallback; - this.request = request; - } - - @Override - public void onResponse(Response response) { - cancelTimeout(); - if (Constants.SUCCESS_CODE.equals(response.getStatus())) { - bizCallback.onResponse(response.getResult()); - } else { - Throwable exception = null; - if (response.getException() != null) { - exception = response.getException(); - } else { - exception = - new StarlightRpcException(response.getStatus(), response.getErrorMsg(), response.getException()); - } - bizCallback.onError(exception); - } - } - - @Override - public void onError(Throwable e) { - cancelTimeout(); - bizCallback.onError(e); - } - - @Override - public Request getRequest() { - return this.request; - } - - @Override - public void addTimeout(Timeout timeout) { - this.timeout = timeout; - } - - private void cancelTimeout() { - if (timeout != null && !timeout.isCancelled()) { - timeout.cancel(); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallback.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallback.java deleted file mode 100644 index 62865ebb..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallback.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.exception.RpcException; -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.util.Timeout; - -/** - * Async Filter Callback 异步过滤链的Callback,包裹BizWrapCallback or FutureCallback Created by liuruisen on 2019/12/8. - */ -public class FilterCallback implements RpcCallback { - - private final Filter filter; - - private final RpcCallback callback; // BizWrapCallback or FutureCallback - - private final Request request; - - public FilterCallback(RpcCallback callback, Filter filter, Request request) { - this.callback = callback; - this.filter = filter; - this.request = request; - } - - @Override - public void onResponse(Response response) { - filter.filterResponse(response, request); - if (callback != null) { - callback.onResponse(response); - } - } - - @Override - public void onError(Throwable e) { - Response response = new RpcResponse(request.getId()); - response.setErrorMsg(e.getMessage()); - if (e instanceof RpcException) { - response.setStatus(((RpcException) e).getCode()); - } - filter.filterResponse(response, request); - if (callback != null) { - callback.onError(e); - } - } - - @Override - public Request getRequest() { - return this.request; - } - - @Override - public void addTimeout(Timeout timeout) { - callback.addTimeout(timeout); - } - - @Override - public void addRpcChannel(RpcChannel rpcChannel) { - callback.addRpcChannel(rpcChannel); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallback.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallback.java deleted file mode 100644 index 266781cc..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallback.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.exception.RpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.thirdparty.netty.util.Timeout; - -/** - * Wrap Future Callback, Async Call: Future mode 用户采用Future的异步调用方式时使用此类(依据用户参数信息进行判断) 在StarlightClient request 前封装 - * Created by liuruisen on 2019/12/8. - */ -public class FutureCallback implements RpcCallback { - private final ResultFuture resultFuture; - - private final Request request; - - private Timeout timeout; - - public FutureCallback(ResultFuture resultFuture, Request request) { - this.resultFuture = resultFuture; - this.request = request; - } - - @Override - public void onResponse(Response response) { - cancelTimeout(); - resultFuture.putResponse(response); - } - - @Override - public void onError(Throwable e) { - cancelTimeout(); - Response response = new RpcResponse(request.getId()); - response.setErrorMsg(e.getMessage()); - response.setProtocolName(request.getProtocolName()); - if (e instanceof RpcException) { - response.setStatus(((RpcException) e).getCode()); - } - resultFuture.putResponse(response); - } - - @Override - public Request getRequest() { - return this.request; - } - - @Override - public void addTimeout(Timeout timeout) { - this.timeout = timeout; - } - - private void cancelTimeout() { - if (timeout != null && !timeout.isCancelled()) { - timeout.cancel(); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/InvokeCallBack.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/InvokeCallBack.java deleted file mode 100644 index 92c1acf7..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/InvokeCallBack.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; - -/** - * Server端 服务调用callback - */ -public class InvokeCallBack extends BaseInvokeCallBack { - - public InvokeCallBack(Request request, RpcChannel context) { - super(request, context); - } - - private volatile boolean isExecuted = false; - - @Override - public void onResponse(Response response) { // service execute return object - if (!isExecuted) { - isExecuted = true; - super.onResponse(response); - } - } - - @Override - public void onError(Throwable e) { // service execute throw exception - if (!isExecuted) { - isExecuted = true; - super.onError(e); - } - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseClientCallBack.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseClientCallBack.java deleted file mode 100644 index d96d8d7c..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseClientCallBack.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.core.rpc.sse.StarlightClientSseEmitter; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * client端 sse响应callback - */ -public class SseClientCallBack implements RpcCallback { - private static final Logger LOGGER = LoggerFactory.getLogger(SseClientCallBack.class); - - private StarlightClientSseEmitter clientSseEmitter; - - private final Request request; - - private Timeout timeout; - - private RpcChannel rpcChannel; - - public SseClientCallBack(StarlightClientSseEmitter clientSseEmitter, Request request) { - this.clientSseEmitter = clientSseEmitter; - this.request = request; - clientSseEmitter.setSseClientCallBack(this); - } - - @Override - public synchronized void onResponse(Response response) { - if (response.getStatus() != Constants.SUCCESS_CODE) { - if (response.getException() != null) { - onError(response.getException()); - } else { - onError( - new StarlightRpcException(response.getStatus(), response.getErrorMsg(), response.getException())); - } - return; - } - cancelTimeout(); - List serverEvents = (List) response.getResult(); - for (ServerEvent serverEvent : serverEvents) { - if (serverEvent == ServerEvent.START_EVENT) { - LOGGER.debug("receive sse response:{}", response); - continue; - } else if (serverEvent == ServerEvent.COMPLETE_EVENT) { - LOGGER.debug("receive sse complete event:{}", response); - clientSseEmitter.triggerOnCompletion(); - closeRpcChannel(); - } else { - LOGGER.debug("receive sse servet event:{}", serverEvent); - clientSseEmitter.pushServerEvent(serverEvent); - } - } - } - - @Override - public synchronized void onError(Throwable e) { - cancelTimeout(); - clientSseEmitter.triggerOnError(e); - closeRpcChannel(); - } - - @Override - public void addTimeout(Timeout timeout) { - this.timeout = timeout; - } - - @Override - public Request getRequest() { - return this.request; - } - - @Override - public void addRpcChannel(RpcChannel rpcChannel) { - this.rpcChannel = rpcChannel; - } - - public void closeRpcChannel() { - if (rpcChannel != null) { - // 从连接池删除连接 - rpcChannel.allCallbacks().clear(); - rpcChannel.removeAttribute(Constants.SSE_CALLBACK_ATTR_KEY); - rpcChannel.removeAttribute(Constants.SSE_EMBEDDED_CHANNEL_KEY); - rpcChannel.removeAttribute(Constants.SSE_REQUEST_ID_KEY); - rpcChannel.getRpcChannelGroup().close(); - } - } - - private void cancelTimeout() { - if (timeout != null && !timeout.isCancelled()) { - timeout.cancel(); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseServerCallBack.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseServerCallBack.java deleted file mode 100644 index 71282e36..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/callback/SseServerCallBack.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Server端 sse服务调用callback - */ -public class SseServerCallBack extends BaseInvokeCallBack { - private static Logger logger = LoggerFactory.getLogger(SseServerCallBack.class); - - public SseServerCallBack(Request request, RpcChannel context) { - super(request, context); - } - - private volatile boolean isErrorExecuted = false; - private volatile boolean isResponseExecuted = false; - - private Throwable throwable; - - @Override - public synchronized void onResponse(Response response) { - if (!isErrorExecuted) { - isResponseExecuted = true; - super.onResponse(response); - } else { - // 错误响应已经返回了 - logger.error("Error occurred while method invoke."); - throw new IllegalStateException("Error occurred while method invoke.", throwable); - } - } - - @Override - public synchronized void onError(Throwable e) { - if (!isResponseExecuted && !isErrorExecuted) { - isErrorExecuted = true; - throwable = e; - super.onError(e); - } else { - // 已经正常响应了 - logger.warn("Response occurred while method invoke."); - throw new IllegalStateException("Response occurred while method invoke.", throwable); - } - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/AsyncGenericService.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/AsyncGenericService.java deleted file mode 100644 index eddfd507..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/AsyncGenericService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.generic; - -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; - -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/4/7. - */ -public interface AsyncGenericService extends GenericService { - - /** - * Async rpc call: Future - * - * @param method - * @param args - * @return - * @throws StarlightRpcException - */ - Future $invokeFuture(String method, Object[] args) throws StarlightRpcException; - - /** - * Async rpc call: Callback - * - * @param method - * @param args method params exclude Callback - * @param callback callback - * @throws StarlightRpcException - */ - void $invokeCallback(String method, Object[] args, Callback callback) throws StarlightRpcException; -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/GenericService.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/GenericService.java deleted file mode 100644 index 22636109..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/generic/GenericService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.generic; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; - -/** - * Created by liuruisen on 2020/4/7. - */ -public interface GenericService { - - /** - * Generic invocation - * - * @param method Method name, e.g. findPerson. Not support overload method - * @param args Arguments - * @return invocation return value - * @throws StarlightRpcException potential exception thrown from the invocation - */ - Object $invoke(String method, Object[] args) throws StarlightRpcException; -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactory.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactory.java deleted file mode 100644 index a94c2c2c..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.proxy.ProxyFactory; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; - -/** - * Created by liuruisen on 2020/2/28. - */ -public class JDKProxyFactory implements ProxyFactory { - - @Override - public T getProxy(Class targetType, ServiceConfig serviceConfig, StarlightClient client) { - client.refer(targetType, serviceConfig); // first refer target service - - InvocationHandler handler = new JdkInvocationHandler(targetType, serviceConfig, client); - T proxy = (T) Proxy.newProxyInstance(targetType.getClassLoader(), new Class[] {targetType}, handler); - return proxy; - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandler.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandler.java deleted file mode 100644 index f6774922..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandler.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.core.rpc.callback.BizWrapCallback; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.core.rpc.callback.SseClientCallBack; -import com.baidu.cloud.starlight.core.rpc.sse.StarlightClientSseEmitter; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.concurrent.Future; - -public class JdkInvocationHandler implements InvocationHandler { - - private static final String FUTURE_SUFFIX = "Future"; - - private static final String CALLBACK_SUFFIX = "Callback"; - - private static final String ASYNC_INTERFACE_SUFFIX = "Async"; - - private final StarlightClient client; - - private final Class targetClass; - - private final ServiceConfig serviceConfig; - - JdkInvocationHandler(Class targetClass, ServiceConfig serviceConfig, StarlightClient client) { - this.client = client; - this.targetClass = targetClass; - this.serviceConfig = serviceConfig; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - - if ("equals".equals(method.getName()) && args.length == 1) { - return equals(args[0]); - } else if ("hashCode".equals(method.getName()) && (args == null || args.length == 0)) { - return hashCode(); - } else if ("toString".equals(method.getName()) && (args == null || args.length == 0)) { - return toString(); - } - RpcCallback rpcCallback = null; - Request request = null; - Class resultType = method.getReturnType(); // return type - if (args != null && args.length > 1 && args[args.length - 1] instanceof Callback) { - Callback bizCallBack = (Callback) args[args.length - 1]; - Object[] realArgs = Arrays.copyOf(args, args.length - 1); - request = buildRequest(targetMethod(method), realArgs); - rpcCallback = new BizWrapCallback(bizCallBack, request); - client.request(request, rpcCallback); - return null; - } else if (RpcSseEmitter.class.isAssignableFrom(resultType)) { - request = buildRequest(targetMethod(method), args); - request.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - StarlightClientSseEmitter clientSseEmitter = new StarlightClientSseEmitter(request); - rpcCallback = new SseClientCallBack(clientSseEmitter, request); - client.request(request, rpcCallback); - return clientSseEmitter; - } else { - request = buildRequest(targetMethod(method), args); - ResultFuture resultFuture = new ResultFuture(); - rpcCallback = new FutureCallback(resultFuture, request); - client.request(request, rpcCallback); - - if (Future.class.isAssignableFrom(resultType)) { - return resultFuture; - } - return resultFuture.get(); - } - } - - private Request buildRequest(Method method, Object[] realArgs) { - Request request = new RpcRequest(); - request.setServiceClass(targetServiceClass(targetClass)); - request.setMethodName(method.getName()); - request.setMethod(method); - request.setParamsTypes(method.getParameterTypes()); - request.setGenericParamsTypes(method.getGenericParameterTypes()); - request.setParams(realArgs); - request.setReturnType(method.getReturnType()); - request.setGenericReturnType(method.getGenericReturnType()); - request.setServiceConfig(serviceConfig); - return request; - } - - protected Method targetMethod(Method proxyMethod) { - if (!isAsyncCall(proxyMethod)) { - return proxyMethod; - } - - Method targetMethod = null; - Class[] proxyParameterTypes = proxyMethod.getParameterTypes(); - Class serviceClass = targetServiceClass(proxyMethod.getDeclaringClass()); - String methodName = proxyMethod.getName(); - - // method end with Future - if (methodName.endsWith(FUTURE_SUFFIX)) { - try { - targetMethod = serviceClass.getMethod(methodName.split(FUTURE_SUFFIX)[0], proxyParameterTypes); - } catch (NoSuchMethodException e) { - throw new StarlightRpcException( - "No related synchronization method in parent class, " + "async method { " + methodName + "}, " - + "related sync method {" + methodName.split("Future")[0] + "}"); - } - } - - // method end with Future - if (methodName.endsWith(CALLBACK_SUFFIX)) { - try { - proxyParameterTypes = Arrays.copyOf(proxyParameterTypes, proxyParameterTypes.length - 1); - targetMethod = serviceClass.getMethod(methodName.split(CALLBACK_SUFFIX)[0], proxyParameterTypes); - } catch (NoSuchMethodException e) { - throw new StarlightRpcException( - "No related synchronization method in parent class, " + "async method { " + methodName + "}, " - + "related sync method {" + methodName.split("Callback")[0] + "}"); - } - } - return targetMethod; - } - - protected Class targetServiceClass(Class proxyClass) { - if (proxyClass.getInterfaces() != null && proxyClass.getInterfaces().length > 0) { - if (proxyClass.getInterfaces().length > 1) { - throw new StarlightRpcException("Starlight not support Multiple inheritance, " - + "Only supports one layer of inheritance when async call"); - } - return proxyClass.getInterfaces()[0]; - } else { - return proxyClass; - } - } - - /** - * 判断本方法是否是异步方法 - * - * @param proxyMethod 未进行最终同步方法转换前的方法 - * @return - */ - protected boolean isAsyncCall(Method proxyMethod) { - - if (targetClass.getInterfaces().length != 1) { // 接口继承层级为1 - return false; - } - - if (!targetClass.getSimpleName().startsWith(ASYNC_INTERFACE_SUFFIX)) { // 接口前缀Async - return false; - } - - String methodName = proxyMethod.getName(); - if (!methodName.endsWith(CALLBACK_SUFFIX) && !methodName.endsWith(FUTURE_SUFFIX)) { - return false; - } - - // callback call, params has one callback - if (methodName.endsWith(CALLBACK_SUFFIX)) { - Class[] paramTypes = proxyMethod.getParameterTypes(); - if (paramTypes.length == 0) { - return false; - } - return Callback.class.isAssignableFrom(paramTypes[paramTypes.length - 1]) - && proxyMethod.getReturnType().equals(Void.TYPE); - } else { // future - return Future.class.isAssignableFrom(proxyMethod.getReturnType()); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/SseEventBuilderImpl.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/SseEventBuilderImpl.java deleted file mode 100644 index ab320a42..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/SseEventBuilderImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.sse; - -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.rpc.sse.SseEventBuilder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; - -import java.nio.charset.StandardCharsets; - -public class SseEventBuilderImpl implements SseEventBuilder { - - private T data; - private String id; - private String event; - private long retry; - private String comment; - - private static final Serializer SERIALIZER = new JsonSerializer(); - - /** - * Add an SSE "id" line. - */ - @Override - public SseEventBuilder id(String id) { - this.id = id; - return this; - } - - /** - * Add an SSE "event" line. - */ - @Override - public SseEventBuilder event(String eventName) { - this.event = eventName; - return this; - } - - /** - * Add an SSE "retry" line. - */ - @Override - public SseEventBuilder retry(long retryMillis) { - this.retry = retryMillis; - return this; - } - - /** - * Add an SSE "comment" line. - */ - @Override - public SseEventBuilder comment(String comment) { - this.comment = comment; - return this; - } - - /** - * Add an SSE "data" line. - */ - @Override - public SseEventBuilder data(T data) { - this.data = data; - return this; - } - - @Override - public ServerEvent build() throws Exception { - ServerEvent serverEvent = new ServerEvent(); - serverEvent.setId(id); - serverEvent.setEvent(event); - serverEvent.setRetry(retry); - serverEvent.setComment(comment); - - if (data instanceof String) { - serverEvent.setData((String) data); - } else { - // data 数据转换成 json string 进行传输 - byte[] serialize = SERIALIZER.serialize(data, data.getClass()); - String dataStr = new String(serialize, StandardCharsets.UTF_8); - serverEvent.setData(dataStr); - } - return serverEvent; - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightClientSseEmitter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightClientSseEmitter.java deleted file mode 100644 index 44446fb2..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightClientSseEmitter.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.sse; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.rpc.sse.SseEventBuilder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.core.rpc.callback.SseClientCallBack; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -public class StarlightClientSseEmitter implements RpcSseEmitter { - - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightClientSseEmitter.class); - private Consumer onError; - private Runnable onCompletion; - private Consumer onServerEvent; - private Consumer onData; - private static final Serializer SERIALIZER = new JsonSerializer(); - private Request request; - private SseClientCallBack sseClientCallBack; - - private Type actualType = Object.class; - - private Throwable earlyError; - - private List earlyServerEvents = new ArrayList<>(); - - public StarlightClientSseEmitter(Request request) { - this.request = request; - - // 获取泛行实际类型 - Type genericReturnType = request.getGenericReturnType(); - if (genericReturnType instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) genericReturnType; - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (actualTypeArguments.length == 1) { - actualType = actualTypeArguments[0]; - } - } - } - - @Override - public void init(RpcCallback rpcCallback) { - throw new UnsupportedOperationException("client not support init()"); - } - - @Override - public void send(T data) throws IOException { - throw new UnsupportedOperationException("client not support send()"); - } - - @Override - public void send(SseEventBuilder builder) throws IOException { - throw new UnsupportedOperationException("client not support send()"); - } - - @Override - public void complete() { - throw new UnsupportedOperationException("client not support complete()"); - } - - @Override - public void completeWithError(Throwable ex) { - throw new UnsupportedOperationException("client not support completeWithError()"); - } - - @Override - public void onTimeout(Runnable callback) { - throw new UnsupportedOperationException("client not support onTimeout()"); - } - - @Override - public synchronized void onError(Consumer callback) { - this.onError = callback; - if (earlyError != null) { - onError.accept(earlyError); - earlyError = null; - } - } - - @Override - public void onCompletion(Runnable callback) { - this.onCompletion = callback; - } - - @Override - public synchronized void onServerEvent(Consumer callback) { - this.onServerEvent = callback; - - earlyServerEvents.forEach(event -> pushServerEvent(event)); - earlyServerEvents.clear(); - } - - @Override - public synchronized void onData(Consumer callback) { - this.onData = callback; - - earlyServerEvents.forEach(event -> pushServerEvent(event)); - earlyServerEvents.clear(); - } - - public synchronized void pushServerEvent(ServerEvent serverEvent) { - try { - if (onServerEvent != null) { - onServerEvent.accept(serverEvent); - } else if (onData != null) { - String data = serverEvent.getData(); - - T t = (T) SERIALIZER.deserialize(data.getBytes(StandardCharsets.UTF_8), actualType); - onData.accept(t); - } else { - LOGGER.warn("no callback treat ServerEvent:{}", serverEvent); - earlyServerEvents.add(serverEvent); - } - } catch (Throwable throwable) { - LOGGER.warn("pushServerEvent fail.", throwable); - } - } - - public void triggerOnCompletion() { - try { - if (onCompletion != null) { - onCompletion.run(); - } - } catch (Throwable throwable) { - LOGGER.warn("triggerOnCompletion fail.", throwable); - } - } - - public synchronized void triggerOnError(Throwable throwable) { - try { - if (onError != null) { - onError.accept(throwable); - } else { - earlyError = throwable; - } - } catch (Throwable t) { - LOGGER.warn("triggerOnError fail.", t); - } - } - - public void setSseClientCallBack(SseClientCallBack sseClientCallBack) { - this.sseClientCallBack = sseClientCallBack; - } - - /** - * 给客户端一个强制断开连接的机会 - */ - @Override - public void close() { - sseClientCallBack.closeRpcChannel(); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightServerSseEmitter.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightServerSseEmitter.java deleted file mode 100644 index cbf8536a..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/sse/StarlightServerSseEmitter.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.sse; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.rpc.sse.SseEventBuilder; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -/** - * Server端的SseEmitter - * - * @param - */ -public class StarlightServerSseEmitter implements RpcSseEmitter { - private static final Logger LOGGER = LoggerFactory.getLogger(StarlightServerSseEmitter.class); - private Timeout timeout; - private long timeoutMills; - - private long lastSendTime = System.currentTimeMillis(); - - private volatile boolean complete = false; - - private volatile Throwable failure; - - private RpcCallback rpcCallback; - - private volatile boolean initialized = false; - - /** - * 如果emitter未初始化之前,发送的数据都会暂存这里 - */ - private final List earlySendAttempts = new ArrayList<>(); - - /** - * 如果emitter未初始化之前,complete标记会暂存这里 - */ - private volatile boolean earlyComplete = false; - - /** - * 如果emitter未初始化之前,completeWithError的错误会暂存这里 - */ - private volatile Throwable earlyFailure; - - /** - * 超时回调 - */ - private Runnable onTimeout; - - /** - * 发送报错的时候回调 - */ - private Consumer onError; - - /** - * emitter完成回调 - */ - private Runnable onCompletion; - - /** - * 是否发送过response - */ - private volatile boolean alreadySendResponse = false; - - public StarlightServerSseEmitter(long timeoutMills) { - this.timeoutMills = timeoutMills; - this.timeout = TimerHolder.getTimer().newTimeout(this::triggerTimeOut, timeoutMills, TimeUnit.MILLISECONDS); - } - - private void triggerTimeOut(Timeout t) { - if (complete) { - return; - } - - try { - long period = System.currentTimeMillis() - lastSendTime; - if (period >= timeoutMills) { - // 超时了 - if (onTimeout != null) { - try { - onTimeout.run(); - } catch (Exception e) { - LOGGER.warn("onTimeout fail.", e); - } - } - - complete(); - } else { - // 没有超时 - this.timeout = t.timer().newTimeout(this::triggerTimeOut, timeoutMills - period, TimeUnit.MILLISECONDS); - } - } catch (Throwable throwable) { - LOGGER.warn("triggerTimeOut fail.", throwable); - } - } - - public static SseEventBuilder event() { - return new SseEventBuilderImpl(); - } - - @Override - public synchronized void init(RpcCallback rpcCallback) { - if (initialized) { - throw new IllegalStateException("StarlightServerSseEmitter already initialized."); - } - initialized = true; - this.rpcCallback = rpcCallback; - - try { - earlySendAttempts.forEach(e -> sendInternal(e)); - } catch (Exception e) { - completeWithError(e); - } finally { - earlySendAttempts.clear(); - } - - if (earlyComplete) { - if (earlyFailure != null) { - completeWithError(earlyFailure); - } else { - complete(); - } - } - - } - - private void checkComplete() { - if (initialized) { - if (complete) { - if (this.failure != null) { - throw new IllegalStateException("StarlightServerSseEmitter has already completedWithError", - failure); - } - throw new IllegalStateException("StarlightServerSseEmitter has already completed"); - } - } else { - if (earlyComplete) { - if (this.earlyFailure != null) { - throw new IllegalStateException("StarlightServerSseEmitter has already completedWithError", - earlyFailure); - } - throw new IllegalStateException("StarlightServerSseEmitter has already completed"); - } - } - - } - - private void sendInternal(ServerEvent serverEvent) { - - lastSendTime = System.currentTimeMillis(); - - if (!initialized) { - earlySendAttempts.add(serverEvent); - return; - } - - if (!alreadySendResponse) { - // 如果还没发送过response,那么就发送开始事件 - alreadySendResponse = true; - sendResponse(ServerEvent.START_EVENT); - } - - sendResponse(serverEvent); - } - - private void sendResponse(ServerEvent serverEvent) { - Request request = rpcCallback.getRequest(); - Response response = new RpcResponse(request.getId()); - response.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult(serverEvent); - response.setReturnType(request.getReturnType()); - response.setGenericReturnType(request.getGenericReturnType()); - - rpcCallback.onResponse(response); - } - - @Override - public synchronized void send(T data) throws IOException { - checkComplete(); - - try { - ServerEvent event = event().data(data).build(); - sendInternal(event); - } catch (Exception e) { - completeWithError(e); - throw new IOException("send event fail.", e); - } - } - - @Override - public synchronized void send(SseEventBuilder builder) throws IOException { - checkComplete(); - - try { - sendInternal(builder.build()); - } catch (Exception e) { - completeWithError(e); - throw new IOException("send event fail.", e); - } - } - - @Override - public synchronized void complete() { - if (!initialized) { - earlyComplete = true; - } - if (complete != true) { - this.complete = true; - if (onCompletion != null) { - try { - onCompletion.run(); - } catch (Exception e) { - LOGGER.warn("onCompletion fail.", e); - } - } - - sendInternal(ServerEvent.COMPLETE_EVENT); - - if (timeout != null) { - timeout.cancel(); - } - } - } - - @Override - public synchronized void completeWithError(Throwable ex) { - if (!initialized) { - earlyComplete = true; - earlyFailure = ex; - } - if (complete != true) { - this.failure = ex; - if (onError != null) { - try { - onError.accept(ex); - } catch (Exception e) { - LOGGER.warn("onError fail.", e); - } - } - - if (alreadySendResponse) { - complete(); - } else { - rpcCallback.onError(ex); - } - } - } - - @Override - public synchronized void onTimeout(Runnable callback) { - this.onTimeout = callback; - } - - @Override - public synchronized void onError(Consumer callback) { - this.onError = callback; - } - - @Override - public synchronized void onCompletion(Runnable callback) { - this.onCompletion = callback; - } - - @Override - public void onServerEvent(Consumer callback) { - throw new UnsupportedOperationException("server not support onServerEvent() callback"); - } - - @Override - public void onData(Consumer callback) { - throw new UnsupportedOperationException("server not support onData() callback"); - } - - @Override - public void close() { - throw new UnsupportedOperationException( - "server not support close() method, please use complete()/completeWithError() method"); - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactory.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactory.java deleted file mode 100644 index 0fdc63c3..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactory.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.threadpool; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/2/13. - */ -public class RpcThreadPoolFactory implements ThreadPoolFactory { - - private final ThreadPoolExecutor defaultThreadPool; - - public RpcThreadPoolFactory(int defaultSize, int maxSize, String prefix) { - - // DEFAULT_BIZ_THREAD_POOL_SIZE - // DEFAULT_MAX_BIZ_THREAD_POOL_SIZE - defaultThreadPool = new ThreadPoolExecutor(defaultSize, maxSize, Constants.IDlE_THREAD_KEEP_ALIVE_SECOND, - TimeUnit.SECONDS, new SynchronousQueue<>(), new NamedThreadFactory(prefix + "-biz-work")); - } - - private final Map threadPoolMap = new ConcurrentHashMap<>(); - - @Override - public ThreadPoolExecutor getThreadPool(RpcService rpcService) { - - // default Thread pool - if (rpcService == null) { - return defaultThreadPool; - } - - if (threadPoolMap.get(rpcService) != null) { - return threadPoolMap.get(rpcService); - } - - if (rpcService.getServiceConfig() != null) { - Integer corePoolSize = rpcService.getServiceConfig().getThreadPoolSize(); - Integer maxThreadPoolSize = rpcService.getServiceConfig().getMaxThreadPoolSize(); - Integer keepAliveTime = rpcService.getServiceConfig().getIdleThreadKeepAliveSecond(); - Integer maxQueueSize = rpcService.getServiceConfig().getMaxRunnableQueueSize(); - - if (corePoolSize != null && maxThreadPoolSize != null && keepAliveTime != null && maxQueueSize != null) { - ThreadPoolExecutor threadPool; - synchronized (this) { - if (threadPoolMap.get(rpcService) != null) { - return threadPoolMap.get(rpcService); - } - threadPool = - new ThreadPoolExecutor(corePoolSize, maxThreadPoolSize, keepAliveTime, TimeUnit.SECONDS, - new LinkedBlockingQueue<>(maxQueueSize), new NamedThreadFactory("service-biz-work")); - threadPoolMap.put(rpcService, threadPool); - } - return threadPool; - } else { - return defaultThreadPool; - } - - } else { // No own thread pool configuration, shared the default thread pool - return defaultThreadPool; - } - } - - @Override - public ThreadPoolExecutor getThreadPool() { - return defaultThreadPool; - } - - @Override - public void close() { - if (threadPoolMap.size() == 0) { - return; - } - for (ThreadPoolExecutor threadPool : threadPoolMap.values()) { - if (!threadPool.isShutdown()) { - threadPool.shutdown(); // shutdown now - } - } - threadPoolMap.clear(); - // fixme default thread pool何时关闭?不手动关闭会有啥影响 - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStats.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStats.java deleted file mode 100644 index 91380e8c..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStats.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.statistics.CountStats; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Objects; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Fixed time window statistics, expires will be cleared Created by liuruisen on 2021/4/18. - */ -public class FixedTimeWindowStats implements CountStats { - - private static final Logger LOGGER = LoggerFactory.getLogger(FixedTimeWindowStats.class); - - private static final int COUNT_INIT_VALUE = 0; - - private long timeWindowSize; // the size of time window: seconds - - private final AtomicReference statsPair; - - public FixedTimeWindowStats(long timeWindowSize) { - this.timeWindowSize = timeWindowSize; - this.statsPair = new AtomicReference<>(new StatsPair()); - } - - @Override - public Integer totalReqCount() { - return recordAndGetReqCount(false, 0).getTotalReqCount(); - } - - @Override - public Integer failReqCount() { - return recordAndGetReqCount(false, 0).getFailReqCount(); - } - - @Override - public Integer sucReqCount() { - StatsPair pair = recordAndGetReqCount(false, 0); - return pair.getTotalReqCount() - pair.getFailReqCount(); - } - - /** - * Set window size, 可用于后序动态更改 - * - * @param timeWindowSize - */ - public void setTimeWindowSize(long timeWindowSize) { - this.timeWindowSize = timeWindowSize; - } - - @Override - public void recordReqCount(boolean success) { - recordAndGetReqCount(success, 1); - } - - @Override - public void record(Request request, Response response) { - boolean success = true; - if (!Constants.SUCCESS_CODE.equals(response.getStatus())) { - if (response.getStatus() > 1000 && response.getStatus() < 3000) { // StarlightRpcExp & TransportExp - success = false; - } - } - - recordReqCount(success); - } - - protected StatsPair recordAndGetReqCount(boolean success, int delta) { - long startRecordTime = System.currentTimeMillis(); - - StatsPair newPair = new StatsPair(); // FIXME 是否会带来GC次数增多 - StatsPair pair = null; - do { - pair = statsPair.get(); - - long timeWinStartTime = pair.getTimeWinStartTime(); - newPair.setTimeWinStartTime(timeWinStartTime); - long nextTimeWindStartTime = System.currentTimeMillis() - (timeWindowSize * 1000); // 预测的下一个时间窗口开始时间 - if (nextTimeWindStartTime > timeWinStartTime) { // 当前时间窗口已到期,开启下一个时间窗 - LOGGER.debug("The current window started at {} is expire , will creat new window", timeWinStartTime); - newPair.setTimeWinStartTime(System.currentTimeMillis()); - newPair.setTotalReqCount(COUNT_INIT_VALUE + delta); - newPair.setFailReqCount(COUNT_INIT_VALUE); - if (!success) { - newPair.setFailReqCount(COUNT_INIT_VALUE + delta); - } - } else { - newPair.setTotalReqCount(pair.getTotalReqCount() + delta); - newPair.setFailReqCount(pair.getFailReqCount()); - if (!success) { - newPair.setFailReqCount(pair.getFailReqCount() + delta); - } - } - } while (!statsPair.compareAndSet(pair, newPair)); // CAS thread-safe - - LOGGER.debug("Get or record stats cost {}", System.currentTimeMillis() - startRecordTime); - return newPair; - } - - /** - * statistics - */ - private static class StatsPair { - private Integer totalReqCount; // TODO 后序接入Metrics框架可使用其定义的类 - - private Integer failReqCount; - - private Long timeWinStartTime; // the timestamp of one fixed time window start time - - public StatsPair() { - this.totalReqCount = 0; - this.failReqCount = 0; - this.timeWinStartTime = System.currentTimeMillis(); - } - - public StatsPair(Integer totalReqCount, Integer failReqCount, Long timestamp) { - this.totalReqCount = totalReqCount; - this.failReqCount = failReqCount; - this.timeWinStartTime = timestamp; - } - - public Integer getTotalReqCount() { - return totalReqCount; - } - - public void setTotalReqCount(Integer totalReqCount) { - this.totalReqCount = totalReqCount; - } - - public Integer getFailReqCount() { - return failReqCount; - } - - public void setFailReqCount(Integer failReqCount) { - this.failReqCount = failReqCount; - } - - public Long getTimeWinStartTime() { - return timeWinStartTime; - } - - public void setTimeWinStartTime(Long timeWinStartTime) { - this.timeWinStartTime = timeWinStartTime; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - StatsPair statsPair = (StatsPair) o; - return Objects.equals(totalReqCount, statsPair.totalReqCount) - && Objects.equals(failReqCount, statsPair.failReqCount) - && Objects.equals(timeWinStartTime, statsPair.timeWinStartTime); - } - - @Override - public int hashCode() { - return Objects.hash(totalReqCount, failReqCount, timeWinStartTime); - } - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatistics.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatistics.java deleted file mode 100644 index 1e86563a..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatistics.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.statistics.Stats; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Starlight统计信息的汇总类 Client维度 Created by liuruisen on 2021/4/19. - */ -public class StarlightStatistics { - - private final Map clientStatsMap; - - public StarlightStatistics() { - this.clientStatsMap = new ConcurrentHashMap<>(); - } - - /** - * Record statistics - * - * @param request - * @param response - */ - public void record(Request request, Response response) { - if (request == null || response == null) { - return; - } - for (Map.Entry clientStatsEntry : clientStatsMap.entrySet()) { - if (clientStatsEntry.getValue() != null) { - clientStatsEntry.getValue().record(request, response); - } - } - } - - /** - * Register stats - * - * @param statsKey statsKey - * @param stats - */ - public void registerStats(String statsKey, Stats stats) { - clientStatsMap.putIfAbsent(statsKey, stats); - } - - /** - * Discover stats by key - * - * @param statsKey - * @return - */ - public Stats discoverStats(String statsKey) { - return clientStatsMap.get(statsKey); - } - - /** - * Remove stats by key - * - * @param statsKey - * @return - */ - public Stats removeStats(String statsKey) { - return clientStatsMap.remove(statsKey); - } -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManager.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManager.java deleted file mode 100644 index 244ae8db..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManager.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.utils.StringUtils; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Created by liuruisen on 2021/4/19. - */ -public class StarlightStatsManager { - - /** - * key: ip:port - * - */ - private static final Map STARLIGHT_STATISTICS_MAP = new ConcurrentHashMap<>(); - - /** - * 参数为uri,考虑的是uri可以携带更多的配置信息 - * - * @param uri - * @return - */ - public static StarlightStatistics getOrCreateStats(URI uri) { - if (uri == null) { - throw new IllegalArgumentException("IP:PORT is empty when used it to create StarlightStats"); - } - String clientKey = uri.getAddress(); // ip:port - if (StringUtils.isEmpty(clientKey)) { - throw new IllegalArgumentException("IP:PORT is empty when used it to create StarlightStats"); - } - StarlightStatistics statistics = STARLIGHT_STATISTICS_MAP.get(clientKey); - if (statistics == null) { - synchronized (StarlightStatsManager.class) { - statistics = STARLIGHT_STATISTICS_MAP.get(clientKey); - if (statistics == null) { - statistics = new StarlightStatistics(); - STARLIGHT_STATISTICS_MAP.put(clientKey, statistics); - } - } - } - - return statistics; - } - - public static StarlightStatistics getStats(URI uri) { - String clientKey = uri.getAddress(); // ip:port - return STARLIGHT_STATISTICS_MAP.get(clientKey); - } - - public static void removeStats(URI uri) { - String clientKey = uri.getAddress(); - STARLIGHT_STATISTICS_MAP.remove(clientKey); - } - - public static StarlightStatistics getOrCreateStatsByHostPort(String hostPort) { - if (StringUtils.isEmpty(hostPort)) { - throw new IllegalArgumentException("IP:PORT is empty when used it to create StarlightStats"); - } - StarlightStatistics statistics = STARLIGHT_STATISTICS_MAP.get(hostPort); - if (statistics == null) { - synchronized (StarlightStatsManager.class) { - statistics = STARLIGHT_STATISTICS_MAP.get(hostPort); - if (statistics == null) { - statistics = new StarlightStatistics(); - STARLIGHT_STATISTICS_MAP.put(hostPort, statistics); - } - } - } - - return statistics; - } - - public static StarlightStatistics getStatsByHostPort(String hostPort) { - return STARLIGHT_STATISTICS_MAP.get(hostPort); - } - - public static void removeStatsByHostPort(String hostPort) { - STARLIGHT_STATISTICS_MAP.remove(hostPort); - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/KeyOrderedExecutor.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/KeyOrderedExecutor.java deleted file mode 100644 index ad38fed2..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/KeyOrderedExecutor.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.utils; - -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * 同一个key的任务,会按照顺序执行的线程池 - */ -public class KeyOrderedExecutor { - private int threadNums; - - private List executorServiceList = new ArrayList<>(); - private static final int DEFAULT_THREAD_NUMS = 16; - - private static final int DEFAULT_BLOCKING_QUEUE_SIZE = 2048; - - public KeyOrderedExecutor(String threadNamePrefix) { - this(DEFAULT_THREAD_NUMS, DEFAULT_BLOCKING_QUEUE_SIZE, threadNamePrefix); - } - - public KeyOrderedExecutor(int threadNums, int blockingQueueSize, String threadNamePrefix) { - if (threadNums <= 0) { - throw new IllegalArgumentException("illegal threadNums"); - } - if (blockingQueueSize <= 0) { - throw new IllegalArgumentException("illegal blockingQueueSize"); - } - if (threadNamePrefix == null) { - throw new IllegalArgumentException("illegal threadNamePrefix"); - } - this.threadNums = threadNums; - NamedThreadFactory namedThreadFactory = new NamedThreadFactory(threadNamePrefix); - - for (int i = 0; i < threadNums; i++) { - executorServiceList.add( - // 要保证有序,必须是单线程的 - new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(blockingQueueSize), - namedThreadFactory)); - } - } - - public void execute(long key, Runnable command) { - int solt = (int) (key % executorServiceList.size()); - executorServiceList.get(solt).execute(command); - } - -} diff --git a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtils.java b/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtils.java deleted file mode 100644 index ab99e90e..00000000 --- a/starlight/starlight-core/src/main/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.utils; - -import com.baidu.cloud.thirdparty.jackson.databind.JsonNode; -import com.baidu.cloud.thirdparty.jackson.databind.ObjectMapper; -import com.baidu.cloud.thirdparty.jackson.databind.node.ArrayNode; -import com.baidu.cloud.thirdparty.jackson.databind.node.ObjectNode; - -import java.lang.reflect.Type; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Map; - -import static com.baidu.cloud.thirdparty.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; - -/** - * Used in generic filter. When filter request, convert generic args to json strings; when filter response, convert json - * strings to real objects. - */ -public class PojoJsonUtils { - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - static { - // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性 - OBJECT_MAPPER.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); - - // 默认时间格式 - SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - OBJECT_MAPPER.setDateFormat(fmt); - } - - /** - * Map or List to Object - * - * @param args - * @param types - * @return - * @throws Exception - */ - public static Object[] realize(Object[] args, Type[] types) throws Exception { - if (args == null) { - return args; - } - if (args.length != types.length) { - throw new IllegalArgumentException("args.length != types.length"); - } - Object[] result = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - if (arg == null) { - continue; - } - if (arg instanceof String) { - if (String.class.equals(types[i])) { - result[i] = arg; - continue; - } - result[i] = OBJECT_MAPPER.readValue((String) arg, OBJECT_MAPPER.constructType(types[i])); - } else { - String json = OBJECT_MAPPER.writeValueAsString(arg); - result[i] = OBJECT_MAPPER.readValue(json, OBJECT_MAPPER.constructType(types[i])); - } - } - return result; - } - - /** - * Object to Map or List - * - * @param data - * @return - * @throws Exception - */ - public static Object generalize(Object data) throws Exception { - if (data == null) { - return data; - } - String json = OBJECT_MAPPER.writeValueAsString(data); - JsonNode jsonNode = OBJECT_MAPPER.readTree(json); - if (jsonNode instanceof ObjectNode) { - return OBJECT_MAPPER.readValue(json, Map.class); - } else if (jsonNode instanceof ArrayNode) { - return OBJECT_MAPPER.readValue(json, List.class); - } else { - return data; - } - } - - public static Object[] toJsonString(Object[] args) throws Exception { - Object[] result = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - result[i] = OBJECT_MAPPER.writeValueAsString(args[i]); - } - return result; - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter b/starlight/starlight-core/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter deleted file mode 100644 index 8e3fff01..00000000 --- a/starlight/starlight-core/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter +++ /dev/null @@ -1,5 +0,0 @@ -com.baidu.cloud.starlight.core.filter.GenericFilter -com.baidu.cloud.starlight.core.filter.ClientMonitorFilter -com.baidu.cloud.starlight.core.filter.ServerMonitorFilter -com.baidu.cloud.starlight.core.filter.ClientContextFilter -com.baidu.cloud.starlight.core.filter.ServerContextFilter \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientContextFilterTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientContextFilterTest.java deleted file mode 100644 index eff66c0e..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientContextFilterTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/9/2. - */ -public class ClientContextFilterTest { - - @Test - public void filterRequest() { - RpcContext.removeContext(); - RpcContext.getContext().set("Key", "Value"); - Invoker invoker = Mockito.mock(Invoker.class); - doNothing().when(invoker).invoke(any(), any()); - RpcCallback callback = Mockito.mock(RpcCallback.class); - Request request = new RpcRequest(1); - ClientContextFilter clientContextFilter = new ClientContextFilter(); - clientContextFilter.filterRequest(invoker, request, callback); - assertNotNull(request.getAttachmentKv()); - assertNotNull(request.getAttachmentKv().get(Constants.SESSION_ID_KEY)); - assertNotNull(request.getAttachmentKv().get(Constants.REQUEST_ID_KEY)); - assertEquals("Value", request.getAttachmentKv().get("Key")); - } - - @Test - public void filterResponse() { - RpcContext.removeContext(); - RpcContext.getContext().set("Key", "Value"); - assertEquals(1, RpcContext.getContext().get().size()); - ClientContextFilter clientContextFilter = new ClientContextFilter(); - clientContextFilter.filterResponse(null, new RpcRequest()); - assertEquals(1, RpcContext.getContext().get().size()); - } - -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilterTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilterTest.java deleted file mode 100644 index 336c10f2..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ClientMonitorFilterTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.core.statistics.FixedTimeWindowStats; -import com.baidu.cloud.starlight.core.statistics.StarlightStatistics; -import com.baidu.cloud.starlight.core.statistics.StarlightStatsManager; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/25. - */ -public class ClientMonitorFilterTest { - - @Test - public void filterResponse() { - RpcRequest rpcRequest = new RpcRequest(); - ClientMonitorFilter monitorFilter = new ClientMonitorFilter(); - monitorFilter.filterResponse(new RpcResponse(), rpcRequest); - - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - URI uri = builder.build(); - rpcRequest.setRemoteURI(uri); - - StarlightStatistics statistics = StarlightStatsManager.getOrCreateStats(uri); - statistics.registerStats("TEST", new FixedTimeWindowStats(10)); - monitorFilter.filterResponse(new RpcResponse(), rpcRequest); - - assertTrue(statistics.discoverStats("TEST") instanceof FixedTimeWindowStats); - assertEquals(0, ((FixedTimeWindowStats) statistics.discoverStats("TEST")).totalReqCount().intValue()); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/FilterChainTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/FilterChainTest.java deleted file mode 100644 index 4edaf6fd..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/FilterChainTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.core.rpc.RpcClientInvoker; -import com.baidu.cloud.starlight.core.rpc.RpcServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.core.rpc.callback.FutureCallback; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class FilterChainTest { - - @Test - public void buildClientChainInvoker() { - ClientInvoker clientInvoker = Mockito.mock(RpcClientInvoker.class); - doNothing().when(clientInvoker).invoke(any(), any()); - clientInvoker = FilterChain.buildClientChainInvoker(clientInvoker, "test,testsame"); - - Request request = new RpcRequest(); - clientInvoker.invoke(request, new FutureCallback(null, request)); - } - - @Test - public void buildServerChainInvoker() { - ServiceInvoker serviceInvoker = Mockito.mock(RpcServiceInvoker.class); - doNothing().when(serviceInvoker).invoke(any(), any()); - serviceInvoker = FilterChain.buildServerChainInvoker(serviceInvoker, "test,testsame"); - Request request = new RpcRequest(); - serviceInvoker.invoke(request, new FutureCallback(null, request)); - } - - @Test - public void buildServerChainIllegal() { - ServiceInvoker serviceInvoker = Mockito.mock(RpcServiceInvoker.class); - doNothing().when(serviceInvoker).invoke(any(), any()); - serviceInvoker = FilterChain.buildServerChainInvoker(serviceInvoker, ""); - Request request = new RpcRequest(); - serviceInvoker.invoke(request, new FutureCallback(null, request)); - - // blank filter - serviceInvoker = FilterChain.buildServerChainInvoker(serviceInvoker, " , "); - - // null filter - serviceInvoker = FilterChain.buildServerChainInvoker(serviceInvoker, null); - - // unSupport filter - try { - serviceInvoker = FilterChain.buildServerChainInvoker(serviceInvoker, "asd"); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalStateException); - } - } - -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/GenericFilterTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/GenericFilterTest.java deleted file mode 100644 index 71905376..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/GenericFilterTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.core.rpc.RpcClientInvoker; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/3/22. - */ -public class GenericFilterTest { - - @Test - public void filterRequest() { - - Request request = new RpcRequest(); - request.setMethodName("filterRequest"); - request.setServiceName(this.getClass().getName()); - Map kv = new HashMap<>(); - kv.put(Constants.IS_GENERIC_KEY, true); - request.setAttachmentKv(kv); - - GenericFilter genericFilter = new GenericFilter(); - genericFilter.filterRequest(new ClientInvoker() { - @Override - public ClientPeer getClientPeer() { - return null; - } - - @Override - public ServiceConfig getServiceConfig() { - return null; - } - - @Override - public void invoke(Request request, RpcCallback callback) { - - } - }, request, new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) { - - } - - @Override - public Request getRequest() { - return null; - } - - @Override - public void onResponse(Response response) { - - } - - @Override - public void onError(Throwable e) { - - } - }); - - assertNull(request.getAttachmentKv().get(Constants.IS_GENERIC_KEY)); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ServerContextFilterTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ServerContextFilterTest.java deleted file mode 100644 index 79ec4e54..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/ServerContextFilterTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Collections; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/9/2. - */ -public class ServerContextFilterTest { - - @Test - public void filterRequest() { - Invoker invoker = Mockito.mock(Invoker.class); - doNothing().when(invoker).invoke(any(), any()); - RpcCallback callback = Mockito.mock(RpcCallback.class); - Request request = new RpcRequest(); - request.setAttachmentKv(Collections.singletonMap("Key", "Value")); - ServerContextFilter serverContextFilter = new ServerContextFilter(); - serverContextFilter.filterRequest(invoker, request, callback); - assertEquals(1, RpcContext.getContext().get().size()); - assertEquals("Value", RpcContext.getContext().get().get("Key")); - } - - @Test - public void filterResponse() { - RpcContext.removeContext(); - RpcContext.getContext().set("Key", "Value"); - assertEquals(1, RpcContext.getContext().get().size()); - ServerContextFilter serverContextFilter = new ServerContextFilter(); - serverContextFilter.filterResponse(null, null); - assertEquals(0, RpcContext.getContext().get().size()); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestFilter.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestFilter.java deleted file mode 100644 index 3535d504..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestFilter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class TestFilter implements Filter { - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestSameFilter.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestSameFilter.java deleted file mode 100644 index 1c96388a..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/filter/TestSameFilter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.filter; - -import com.baidu.cloud.starlight.api.filter.Filter; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.Invoker; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class TestSameFilter implements Filter { - - @Override - public void filterRequest(Invoker invoker, Request request, RpcCallback callback) { - invoker.invoke(request, callback); - } - - @Override - public void filterResponse(Response response, Request request) { - - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest.java deleted file mode 100644 index dd41836b..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.DefaultStarlightServer; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; -import com.baidu.cloud.starlight.core.integrate.model.ExtInfo; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.core.integrate.service.AsyncUserService; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import org.junit.Assert; -import org.junit.Test; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/3/6. - */ -public class StarlightIntegrateTest { - - @Test - public void integrate() throws Exception { - // init starlight server - TransportConfig transportConfig = new TransportConfig(); - transportConfig.setIoThreadNum(8); - transportConfig.setAcceptThreadNum(1); - transportConfig.setWriteTimeoutMills(3000); - transportConfig.setAllIdleTimeout(4000); - StarlightServer starlightServer = new DefaultStarlightServer("localhost", 8005, transportConfig); - starlightServer.init(); - - // export service - starlightServer.export(UserService.class, new UserServiceImpl()); - // serve - starlightServer.serve(); - - /** Client **/ - TransportConfig config = new TransportConfig(); - config.setIoThreadNum(8); - config.setWriteTimeoutMills(3000); - config.setReadIdleTimeout(5000); - config.setConnectTimeoutMills(3000); - config.setReadIdleTimeout(100); - config.setMaxHeartbeatTimes(3); - config.setChannelType("pool"); - StarlightClient starlightClient = new SingleStarlightClient("localhost", 8005, config); - - starlightClient.init(); - - ServiceConfig clientConfig = new ServiceConfig(); - clientConfig.setProtocol("brpc"); - - JDKProxyFactory proxyFactory = new JDKProxyFactory(); - UserService userService = proxyFactory.getProxy(UserService.class, clientConfig, starlightClient); - - User user = userService.getUser(1l); - System.out.println("Sync getUser: " + user); - Assert.assertEquals(user.getUserId(), 1l); - - AsyncUserService asyncUserService = - proxyFactory.getProxy(AsyncUserService.class, clientConfig, starlightClient); - Future future = asyncUserService.getUserFuture(2l); - System.out.println("Future getUser: " + future.get()); - Assert.assertEquals(future.get().getUserId(), 2l); - - Callback callback = new Callback() { - @Override - public void onResponse(User response) { - System.out.println("Callback getUser: " + response); - Assert.assertEquals(response.getUserId(), 3l); - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - } - }; - asyncUserService.getUserCallback(3l, callback); - - // delete user - userService.deleteUser(1l); - - User user1 = new User(); - user1.setUserId(123123); - user1.setUserName("User1"); - user1.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user1.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user1.setExtInfos(extInfos); - - // save user - Long userId = userService.saveUser(user1); - System.out.println("Save user userId: " + userId); - Assert.assertTrue(userId == 123123l); - - User user2 = userService.updateUser(user1); - System.out.println("Update user: " + user2); - Assert.assertTrue(user2.getUserName().equals("User1")); - - starlightClient.destroy(); - starlightServer.destroy(); - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest2.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest2.java deleted file mode 100644 index d21a6c28..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/StarlightIntegrateTest2.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.StarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.core.integrate.service.UserSseService; -import com.baidu.cloud.starlight.core.integrate.service.UserSseServiceImpl; -import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient; -import com.baidu.cloud.starlight.core.rpc.DefaultStarlightServer; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory; -import com.baidu.cloud.starlight.core.integrate.model.User; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -public class StarlightIntegrateTest2 { - - // @Test - public void startServer() throws Exception { - // init starlight server - TransportConfig transportConfig = new TransportConfig(); - transportConfig.setIoThreadNum(8); - transportConfig.setAcceptThreadNum(1); - transportConfig.setWriteTimeoutMills(3000); - transportConfig.setAllIdleTimeout(4000); - StarlightServer starlightServer = new DefaultStarlightServer("localhost", 8005, transportConfig); - starlightServer.init(); - - // export service - starlightServer.export(UserSseService.class, new UserSseServiceImpl()); - // serve - starlightServer.serve(); - - Thread.currentThread().join(); - } - - @Test - public void integrate() throws Exception { - // init starlight server - TransportConfig transportConfig = new TransportConfig(); - transportConfig.setIoThreadNum(8); - transportConfig.setAcceptThreadNum(1); - transportConfig.setWriteTimeoutMills(3000); - transportConfig.setAllIdleTimeout(4000); - StarlightServer starlightServer = new DefaultStarlightServer("localhost", 8005, transportConfig); - starlightServer.init(); - - // export service - starlightServer.export(UserSseService.class, new UserSseServiceImpl()); - // serve - starlightServer.serve(); - - /** Client **/ - TransportConfig config = new TransportConfig(); - config.setIoThreadNum(8); - config.setWriteTimeoutMills(3000); - config.setReadIdleTimeout(5000); - config.setConnectTimeoutMills(3000); - config.setReadIdleTimeout(100); - config.setMaxHeartbeatTimes(3); - config.setChannelType("pool"); - StarlightClient starlightClient = new SingleStarlightClient("localhost", 8005, config); - - starlightClient.init(); - - ServiceConfig clientConfig = new ServiceConfig(); - clientConfig.setProtocol("springrest"); - - JDKProxyFactory proxyFactory = new JDKProxyFactory(); - UserSseService userService = proxyFactory.getProxy(UserSseService.class, clientConfig, starlightClient); - - for (int i = 0; i < 20; i++) { - List userList = new ArrayList<>(); - CountDownLatch countDownLatch = new CountDownLatch(1); - RpcSseEmitter sseEmitter = userService.getUserList(); - sseEmitter.onData(u -> { - Assert.assertNotNull(u); - userList.add(u); - }); - sseEmitter.onError(t -> { - t.printStackTrace(); - countDownLatch.countDown(); - }); - - sseEmitter.onCompletion(() -> { - countDownLatch.countDown(); - }); - countDownLatch.await(); - - Assert.assertTrue(userList.size() == 5); - } - - User user = new User(); - user.setUserId(1123); - user.setUserName("test"); - user = userService.addUser(user); - - Assert.assertNotNull(user); - - starlightClient.destroy(); - starlightServer.destroy(); - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/ExtInfo.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/ExtInfo.java deleted file mode 100644 index 35e0c1c9..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/ExtInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.model; - -public class ExtInfo { - private String key; - - private Object value; - - public ExtInfo() { - - } - - public ExtInfo(String key, Object value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ExtInfo{"); - sb.append("key='").append(key).append('\''); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/User.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/User.java deleted file mode 100644 index f3093b74..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/model/User.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.model; - -import java.util.List; - -/** - * Created by liuruisen on 2020/3/6. - */ -public class User { - - private long userId; - - private String userName; - - private double balance; - - private List tags; - - private List extInfos; - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public List getExtInfos() { - return extInfos; - } - - public void setExtInfos(List extInfos) { - this.extInfos = extInfos; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("User{"); - sb.append("userId=").append(userId); - sb.append(", userName='").append(userName).append('\''); - sb.append(", balance=").append(balance); - sb.append(", tags=").append(tags); - sb.append(", extInfos=").append(extInfos); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/AsyncUserService.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/AsyncUserService.java deleted file mode 100644 index fc3411ea..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/AsyncUserService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.service; - -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; - -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/3/11. - */ -public interface AsyncUserService extends UserService { - - void getUserCallback(Long userId, Callback callback); - - Future getUserFuture(Long userId); -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserService.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserService.java deleted file mode 100644 index 38f5b6a5..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.service; - -import com.baidu.cloud.starlight.core.integrate.model.User; - -/** - * Created by liuruisen on 2020/3/6. - */ -public interface UserService { - - User getUser(Long userId); - - User updateUser(User user); - - void deleteUser(Long userId); - - Long saveUser(User user); -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserServiceImpl.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserServiceImpl.java deleted file mode 100644 index 8aafdcf8..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.service; - -import com.baidu.cloud.starlight.core.integrate.model.ExtInfo; -import com.baidu.cloud.starlight.core.integrate.model.User; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/6. - */ -public class UserServiceImpl implements UserService { - - @Override - public User getUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - return user; - } - - @Override - public User updateUser(User user) { - return user; - } - - @Override - public void deleteUser(Long userId) { - try { - TimeUnit.SECONDS.sleep(2); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Delete user {" + userId + "}"); - } - - @Override - public Long saveUser(User user) { - return user.getUserId(); - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseService.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseService.java deleted file mode 100644 index d1ae49e2..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.service; - -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; - -public interface UserSseService { - - @GetMapping("user/getUserList") - RpcSseEmitter getUserList(); - - @PostMapping("user/addUser") - User addUser(@RequestBody User user); - -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseServiceImpl.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseServiceImpl.java deleted file mode 100644 index 970bc2d6..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/integrate/service/UserSseServiceImpl.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.integrate.service; - -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.core.integrate.model.ExtInfo; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.core.rpc.sse.StarlightServerSseEmitter; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class UserSseServiceImpl implements UserSseService { - @Override - public RpcSseEmitter getUserList() { - RpcSseEmitter sseEmitter = new StarlightServerSseEmitter<>(5 * 60 * 1000); - - try { - sseEmitter.send(genUser(1L)); - sseEmitter.send(genUser(2L)); - } catch (IOException e) { - throw new RuntimeException(e); - } - - Thread thread = new Thread(() -> { - try { - TimeUnit.SECONDS.sleep(1); - for (int i = 0; i < 3; i++) { - sseEmitter.send(genUser(i + 3L)); - } - sseEmitter.complete(); - } catch (Exception e) { - e.printStackTrace(); - } - }); - thread.start(); - return sseEmitter; - } - - @Override - public User addUser(User user) { - return user; - } - - User genUser(Long userId) { - User user = new User(); - user.setUserId(userId); - user.setUserName("User1"); - user.setBalance(1000.21d); - List tags = new LinkedList<>(); - tags.add("fgh"); - tags.add("123123"); - user.setTags(tags); - List extInfos = new LinkedList<>(); - ExtInfo extInfo = new ExtInfo("hobby", "learn"); - extInfos.add(extInfo); - user.setExtInfos(extInfos); - return user; - } -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ClientProcessorTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ClientProcessorTest.java deleted file mode 100644 index f427a598..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ClientProcessorTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.core.rpc.threadpool.RpcThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class ClientProcessorTest { - - private ClientProcessor clientProcessor = new ClientProcessor(new RpcThreadPoolFactory(0, 2, "c")); - - @Test - public void getRegistry() { - try { - clientProcessor.getRegistry(); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - } - - @Test - public void process() throws InterruptedException { - Response response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult(new User()); - - RpcCallback rpcCallback = new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) {} - - @Override - public Request getRequest() { - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceClass(UserService.class); - request.setServiceConfig(new ServiceConfig()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - request.setParamsTypes(new Class[] {Long.class}); - request.setReturnType(User.class); - return request; - } - - @Override - public void onResponse(Response response) { - Assert.assertTrue(response.getStatus() == Constants.SUCCESS_CODE); - } - - @Override - public void onError(Throwable e) { - - } - }; - RpcChannel rpcChannel = Mockito.mock(RpcChannel.class); - doReturn(rpcCallback).when(rpcChannel).removeCallback(anyLong()); - clientProcessor.process(response, rpcChannel); - TimeUnit.SECONDS.sleep(1); - Assert.assertTrue(clientProcessor.completeCount(UserService.class.getName()) >= 1); - } - - @Test - public void processError() throws InterruptedException { - - Response response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult(new User()); - - RpcCallback rpcCallback = new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) {} - - @Override - public Request getRequest() { - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceClass(UserService.class); - request.setServiceConfig(new ServiceConfig()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - request.setParamsTypes(new Class[] {Long.class}); - // request.setBodyType(User.class); - return request; - } - - @Override - public void onResponse(Response response) { - Assert.assertTrue(response.getStatus() == Constants.SUCCESS_CODE); - } - - @Override - public void onError(Throwable e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - }; - RpcChannel rpcChannel = Mockito.mock(RpcChannel.class); - doReturn(rpcCallback).when(rpcChannel).removeCallback(anyLong()); - clientProcessor.process(response, rpcChannel); - - TimeUnit.SECONDS.sleep(1); - - try { - clientProcessor.process(new RpcRequest(), rpcChannel); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - clientProcessor.close(); - } - - @Test - public void waitTaskCount() { - Assert.assertTrue(clientProcessor.waitTaskCount(UserService.class.getName()) == 0); - } - - @Test - public void processingCount() { - Assert.assertTrue(clientProcessor.processingCount(UserService.class.getName()) == 0); - } - - @Test - public void allWaitTaskCount() { - Assert.assertEquals(Integer.valueOf(0), clientProcessor.allWaitTaskCount()); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightClientTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightClientTest.java deleted file mode 100644 index 997d765a..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightClientTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.rpc.ClientInvoker; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.core.rpc.callback.BizWrapCallback; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.core.integrate.service.AsyncUserService; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.transport.netty.NettyClient; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class DefaultStarlightClientTest { - - private SingleStarlightClient starlightClient; - - @Before - public void before() { - TransportConfig transportConfig = new TransportConfig(); - transportConfig.setAcceptThreadNum(1); - transportConfig.setIoThreadNum(2); - transportConfig.setAllIdleTimeout(100); - transportConfig.setConnectTimeoutMills(1000); - transportConfig.setWriteTimeoutMills(1000); - starlightClient = new SingleStarlightClient("localhost", 8005, transportConfig); - } - - @Test - public void init() throws NoSuchFieldException, IllegalAccessException { - try { - starlightClient.init(); - } catch (Exception e) { - e.printStackTrace(); - } - - Field field = starlightClient.getClass().getDeclaredField("clientPeer"); - field.setAccessible(true); - ClientPeer ClientPeer = (ClientPeer) field.get(starlightClient); - Assert.assertNotNull(ClientPeer); - Assert.assertTrue(ClientPeer instanceof NettyClient); - } - - @Test - public void refer() throws IllegalAccessException, NoSuchFieldException { - try { - starlightClient.init(); - } catch (Exception e) { - e.printStackTrace(); - } - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setThreadPoolSize(123); - starlightClient.refer(UserService.class, serviceConfig); - - Field field = starlightClient.getClass().getDeclaredField("clientInvokers"); - field.setAccessible(true); - Map map = (Map) field.get(starlightClient); - Assert.assertTrue(map.size() >= 1); - - // refer illegal - starlightClient.refer(AsyncUserService.class, serviceConfig); - Assert.assertTrue(map.size() >= 1); - - starlightClient.destroy(); - Assert.assertTrue(map.size() == 0); - } - - @Test - public void request() throws NoSuchFieldException, IllegalAccessException { - try { - starlightClient.init(); - } catch (Exception e) { - e.printStackTrace(); - } - Field field = starlightClient.getClass().getDeclaredField("clientPeer"); - field.setAccessible(true); - ClientPeer ClientPeer = (ClientPeer) field.get(starlightClient); - ClientPeer.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - - Map clientInvokers = new HashMap<>(); - ClientInvoker clientInvoker = Mockito.mock(ClientInvoker.class); - doNothing().when(clientInvoker).invoke(any(), any()); - clientInvokers.put(UserService.class.getName(), clientInvoker); - - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceClass(UserService.class); - request.setServiceConfig(new ServiceConfig()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - request.setParamsTypes(new Class[] {Long.class}); - starlightClient.request(request, new BizWrapCallback(new Callback() { - @Override - public void onResponse(Object response) {} - - @Override - public void onError(Throwable e) {} - }, request)); - } - - @Test - public void requestError() throws NoSuchFieldException, IllegalAccessException { - try { - starlightClient.init(); - } catch (Exception e) { - e.printStackTrace(); - } - Field field = starlightClient.getClass().getDeclaredField("clientPeer"); - field.setAccessible(true); - ClientPeer ClientPeer = (ClientPeer) field.get(starlightClient); - ClientPeer.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceClass(UserService.class); - request.setServiceConfig(new ServiceConfig()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - request.setParamsTypes(new Class[] {Long.class}); - starlightClient.request(request, new BizWrapCallback(new Callback() { - @Override - public void onResponse(Object response) {} - - @Override - public void onError(Throwable e) { - Assert.assertTrue(e instanceof StarlightRpcException); - Assert.assertTrue(((StarlightRpcException) e).getCode() == StarlightRpcException.BAD_REQUEST); - } - }, request)); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServerTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServerTest.java deleted file mode 100644 index adfb4613..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/DefaultStarlightServerTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.config.TransportConfig; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.transport.netty.NettyServer; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class DefaultStarlightServerTest { - - private DefaultStarlightServer starlightServer; - private TransportConfig transportConfig; - - @Before - public void before() { - transportConfig = new TransportConfig(); - transportConfig.setAcceptThreadNum(1); - transportConfig.setIoThreadNum(2); - transportConfig.setAllIdleTimeout(100); - transportConfig.setConnectTimeoutMills(1000); - transportConfig.setWriteTimeoutMills(1000); - starlightServer = new DefaultStarlightServer("brpc", "localhost", 8001, transportConfig); - - } - - @Ignore - @Test - public void init() throws NoSuchFieldException, IllegalAccessException { - - starlightServer.init(); - Field field = starlightServer.getClass().getDeclaredField("serverPeer"); - field.setAccessible(true); - ServerPeer serverPeer = (ServerPeer) field.get(starlightServer); - Assert.assertNotNull(serverPeer); - Assert.assertTrue(serverPeer instanceof NettyServer); - starlightServer.destroy(); - } - - @Ignore - @Test - public void serve() throws NoSuchFieldException, IllegalAccessException, InterruptedException { - starlightServer.init(); - starlightServer.serve(); - - Field field = starlightServer.getClass().getDeclaredField("serverPeer"); - field.setAccessible(true); - ServerPeer serverPeer = (ServerPeer) field.get(starlightServer); - Assert.assertNotNull(serverPeer); - Assert.assertTrue(serverPeer instanceof NettyServer); - Assert.assertTrue(serverPeer.isBound()); - - starlightServer.destroy(); - TimeUnit.SECONDS.sleep(2); - Assert.assertFalse(serverPeer.isBound()); - } - - @Test - public void export() { - starlightServer.init(); - starlightServer.export(UserService.class, new UserServiceImpl()); - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl()); - Assert.assertNotNull(RpcServiceRegistry.getInstance().discover(rpcService.getServiceName())); - starlightServer.destroy(); - } - - @Ignore - @Test - public void testExport() { - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setThreadPoolSize(1); - starlightServer.init(); - starlightServer.export(UserService.class, new UserServiceImpl(), serviceConfig); - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl(), serviceConfig); - Assert.assertNotNull(RpcServiceRegistry.getInstance().discover(rpcService.getServiceName())); - } - - @Ignore - @Test - public void unexport() { - starlightServer.export(UserService.class, new UserServiceImpl()); - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl()); - Assert.assertNotNull(RpcServiceRegistry.getInstance().discover(rpcService.getServiceName())); - starlightServer.unexport(rpcService); - Assert.assertNull(RpcServiceRegistry.getInstance().discover(rpcService.getServiceName())); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvokerTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvokerTest.java deleted file mode 100644 index 7eed4069..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcClientInvokerTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class RpcClientInvokerTest { - - private RpcClientInvoker clientInvoker; - - @Before - public void before() { - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setServiceId(UserService.class.getName()); - serviceConfig.setProtocol("brpc"); - - ClientPeer clientPeer = Mockito.mock(ClientPeer.class); - doNothing().when(clientPeer).request(any(), any()); - clientInvoker = new RpcClientInvoker(clientPeer, serviceConfig); - } - - @Test - public void getClientPeer() { - Assert.assertNotNull(clientInvoker.getClientPeer()); - } - - @Test - public void invoke() { - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceClass(UserService.class); - request.setParams(new Object[] {1l}); - request.setParamsTypes(new Class[] {Long.class}); - request.setProtocolName("brpc"); - request.setReturnType(User.class); - clientInvoker.invoke(request, null); - } - - @Test - public void destroy() { - clientInvoker.destroy(); - } - - @Test - public void init() { - clientInvoker.init(); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvokerTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvokerTest.java deleted file mode 100644 index 525ad6f4..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceInvokerTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class RpcServiceInvokerTest { - - private RpcServiceInvoker rpcServiceInvoker; - - @Before - public void before() { - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl()); - rpcServiceInvoker = new RpcServiceInvoker(rpcService); - } - - @Test - public void getRpcService() { - assertEquals(rpcServiceInvoker.getRpcService().getServiceName(), UserService.class.getName()); - } - - @Test - public void invoke() { - Request request = new RpcRequest(); - request.setMethodName("getUser1"); - request.setServiceName("normal:" + UserService.class.getName() + ":1.0.0"); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - - RpcCallback rpcCallback = new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) {} - - @Override - public Request getRequest() { - return request; - } - - @Override - public void onResponse(Response response) { - Assert.assertTrue(response.getResult() instanceof User); - assertEquals(((User) response.getResult()).getUserId(), 1l); - } - - @Override - public void onError(Throwable e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - }; - rpcServiceInvoker.invoke(request, rpcCallback); - - request.setMethodName("getUser"); - rpcServiceInvoker.invoke(request, rpcCallback); - - request.setParams(new Object[] {"1"}); - rpcServiceInvoker.invoke(request, rpcCallback); - } - - @Test - public void destroy() { - rpcServiceInvoker.destroy(); - } - - @Test - public void init() { - rpcServiceInvoker.init(); - } - - @Test - public void convertThrowable() throws NoSuchMethodException { - - Method illArguMethod = this.getClass().getMethod("throwException", Integer.class); - try { - illArguMethod.invoke(this, "123"); // IllegalArgumentException - } catch (Throwable e) { - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(e); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(IllegalArgumentException.class.getSimpleName())); - } - - Method illAccMeth = this.getClass().getDeclaredMethod("illegalAccException"); - try { - illAccMeth.invoke(this); // IllegalAccessExp - } catch (Throwable e) { - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(e); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(IllegalAccessException.class.getSimpleName())); - } - - Method throwErrMeth = this.getClass().getDeclaredMethod("throwError"); - try { - throwErrMeth.invoke(this); // Error - } catch (Throwable e) { - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(e); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(StackOverflowError.class.getSimpleName())); - } - - Method throwExpMeth = this.getClass().getMethod("throwException", Integer.class); - try { - throwExpMeth.invoke(this, 1); // exception - } catch (Throwable e) { - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(e); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(Exception.class.getSimpleName())); - assertTrue(starlightRpcException.getMessage().contains("Exception test")); - } - - Method throwNpeMeth = this.getClass().getMethod("throwNPE"); - try { - throwNpeMeth.invoke(this); - } catch (Throwable e) { - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(e); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(NullPointerException.class.getSimpleName())); - } - - StarlightRpcException starlightRpcException = rpcServiceInvoker.convertThrowable(new Exception()); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException.getCode()); - assertTrue(starlightRpcException.getMessage().contains(Exception.class.getSimpleName())); - - StarlightRpcException starlightRpcException1 = - rpcServiceInvoker.convertThrowable(new Exception(new Exception("Error1111"))); - assertEquals(StarlightRpcException.BIZ_ERROR, starlightRpcException1.getCode()); - assertTrue(starlightRpcException1.getMessage().contains("Error1111")); - } - - public void throwException(Integer index) throws Exception { - throw new Exception("Exception test"); - } - - public void throwNPE() { - throw new NullPointerException(); - } - - private void illegalAccException() {} - - public void throwError() { - throw new StackOverflowError(); - } - -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistryTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistryTest.java deleted file mode 100644 index 0004c51a..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/RpcServiceRegistryTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class RpcServiceRegistryTest { - - @Test - public void registerUnRegister() { - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - registry.destroy(); - ServiceInvoker serviceInvoker = new RpcServiceInvoker(new RpcService(UserService.class, new UserServiceImpl())); - - registry.unRegister(serviceInvoker); - Assert.assertEquals(registry.rpcServices().size(), 0); - - registry.register(serviceInvoker); - Assert.assertEquals(registry.rpcServices().size(), 1); - - registry.unRegister(serviceInvoker); - Assert.assertEquals(registry.rpcServices().size(), 0); - } - - @Test - public void discover() { - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - registry.destroy(); - ServiceInvoker serviceInvoker = new RpcServiceInvoker(new RpcService(UserService.class, new UserServiceImpl())); - registry.unRegister(serviceInvoker); - registry.register(serviceInvoker); - Assert.assertEquals(registry.rpcServices().size(), 1); - - ServiceInvoker result = - registry.discover(new RpcService(UserService.class, new UserServiceImpl()).getServiceName()); - Assert.assertEquals(result.getRpcService().getServiceName(), UserService.class.getName()); - } - - @Test - public void rpcServices() { - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - registry.destroy(); - ServiceInvoker serviceInvoker = new RpcServiceInvoker(new RpcService(UserService.class, new UserServiceImpl())); - registry.unRegister(serviceInvoker); - registry.register(serviceInvoker); - - Assert.assertEquals(registry.rpcServices().size(), 1); - } - - @Test - public void destroy() { - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - registry.destroy(); - Assert.assertEquals(registry.rpcServices().size(), 0); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ServerProcessorTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ServerProcessorTest.java deleted file mode 100644 index 087add01..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/ServerProcessorTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc; - -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceInvoker; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.core.rpc.threadpool.RpcThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class ServerProcessorTest { - - private ServerProcessor serverProcessor; - - @Before - public void before() { - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setInvokeTimeoutMills(1000); - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl(), serviceConfig); - - ServiceInvoker invoker = registry.discover(rpcService.getServiceName()); - if (invoker == null) { - invoker = new RpcServiceInvoker(rpcService); - registry.register(invoker); - } - - serverProcessor = new ServerProcessor(registry, new RpcThreadPoolFactory(0, 10, "s")); - } - - @Test - public void getRegistry() { - Assert.assertEquals(serverProcessor.getRegistry().rpcServices().size(), 1); - } - - @Test - public void process() throws InterruptedException { - Request request = new RpcRequest(); - request.setMethodName("getUser"); - request.setServiceName(UserService.class.getName()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - - RpcChannel rpcChannel = Mockito.mock(RpcChannel.class); - doNothing().when(rpcChannel).send(any()); - serverProcessor.setThreadPoolFactory(new RpcThreadPoolFactory(0, 10, "s")); - serverProcessor.process(request, rpcChannel); - - TimeUnit.SECONDS.sleep(2); - - Assert.assertTrue(serverProcessor.completeCount(request.getServiceName()) > 0); - } - - @Test - public void processError() throws InterruptedException { - Request request = new RpcRequest(); - request.setMethodName("getUser1"); - request.setServiceName(UserService.class.getName()); - request.setProtocolName("brpc"); - request.setParams(new Object[] {1l}); - - RpcChannel rpcChannel = Mockito.mock(RpcChannel.class); - doNothing().when(rpcChannel).send(any()); - serverProcessor.setThreadPoolFactory(new RpcThreadPoolFactory(0, 10, "s")); - // no such method - serverProcessor.process(request, rpcChannel); - - TimeUnit.SECONDS.sleep(2); - Assert.assertTrue(serverProcessor.completeCount(request.getServiceName()) > 0); - - RpcServiceRegistry registry = RpcServiceRegistry.getInstance(); - ServiceInvoker serviceInvoker = registry.discover(UserService.class.getName()); - RpcService rpcService = serviceInvoker.getRpcService(); - rpcService.getServiceConfig().setInvokeTimeoutMills(1); - - Request request2 = new RpcRequest(); - request2.setMethodName("deleteUser"); - request2.setServiceName(UserService.class.getName()); - request2.setProtocolName("brpc"); - request2.setParams(new Object[] {1l}); - - // timeout - serverProcessor.process(request2, rpcChannel); - - TimeUnit.SECONDS.sleep(5); - Assert.assertTrue(serverProcessor.completeCount(request2.getServiceName()) > 0); - - // process null - try { - serverProcessor.process(new RpcResponse(), rpcChannel); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - } - - @Test - public void close() { - serverProcessor.close(); - } - - @Test - public void waitTaskCount() { - serverProcessor.setThreadPoolFactory(new RpcThreadPoolFactory(0, 10, "s")); - Assert.assertEquals(0, (int) serverProcessor.waitTaskCount(UserService.class.getName())); - } - - @Test - public void processingCount() { - serverProcessor.setThreadPoolFactory(new RpcThreadPoolFactory(0, 10, "s")); - Assert.assertEquals(0, (int) serverProcessor.processingCount(UserService.class.getName())); - } - - @Test - public void allWaitTaskCount() { - serverProcessor.setThreadPoolFactory(new RpcThreadPoolFactory(0, 10, "s")); - Assert.assertEquals(0, (int) serverProcessor.allWaitTaskCount()); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallbackTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallbackTest.java deleted file mode 100644 index 6119764a..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/BizWrapCallbackTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class BizWrapCallbackTest { - - private Callback callback; - - private Request request; - - private Response response; - - private Timeout timeout; - - @Before - public void before() { - callback = new Callback() { - @Override - public void onResponse(Object response) { - System.out.println(response); - Assert.assertTrue(response.equals("Test")); - } - - @Override - public void onError(Throwable e) { - Assert.assertTrue(e instanceof StarlightRpcException); - Assert.assertTrue(((StarlightRpcException) e).getCode() == StarlightRpcException.INTERNAL_SERVER_ERROR); - } - }; - - timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - System.out.println("Timeout"); - } - }, 3, TimeUnit.SECONDS); - - request = new RpcRequest(); - response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult("Test"); - } - - @Test - public void onResponse() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - bizWrapCallback.addTimeout(timeout); - bizWrapCallback.onResponse(response); - bizWrapCallback.onResponse(response); - } - - @Test - public void onError() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - bizWrapCallback.addTimeout(timeout); - bizWrapCallback - .onError(new StarlightRpcException(StarlightRpcException.INTERNAL_SERVER_ERROR, "Internal server error")); - } - - @Test - public void getRequest() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - Assert.assertEquals(bizWrapCallback.getRequest(), request); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallbackTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallbackTest.java deleted file mode 100644 index 79efdd5b..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FilterCallbackTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.core.filter.TestFilter; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class FilterCallbackTest { - - private Callback callback; - - private Request request; - - private Response response; - - private Timeout timeout; - - @Before - public void before() { - callback = new Callback() { - @Override - public void onResponse(Object response) { - System.out.println(response); - Assert.assertTrue(response.equals("Test")); - } - - @Override - public void onError(Throwable e) { - Assert.assertTrue(e instanceof StarlightRpcException); - Assert.assertTrue(((StarlightRpcException) e).getCode() == StarlightRpcException.INTERNAL_SERVER_ERROR); - } - }; - - timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - System.out.println("Timeout"); - } - }, 3, TimeUnit.SECONDS); - - request = new RpcRequest(); - response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult("Test"); - } - - @Test - public void onResponse() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - FilterCallback filterCallback = new FilterCallback(bizWrapCallback, new TestFilter(), request); - filterCallback.addTimeout(timeout); - filterCallback.onResponse(response); - } - - @Test - public void onResponseCallbackNull() { - FilterCallback filterCallback = new FilterCallback(null, new TestFilter(), request); - filterCallback.onResponse(response); - } - - @Test - public void onError() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - FilterCallback filterCallback = new FilterCallback(bizWrapCallback, new TestFilter(), request); - filterCallback.addTimeout(timeout); - filterCallback - .onError(new StarlightRpcException(StarlightRpcException.INTERNAL_SERVER_ERROR, "Internal server error")); - } - - @Test - public void onErrorCallbackNull() { - FilterCallback filterCallback = new FilterCallback(null, new TestFilter(), request); - filterCallback - .onError(new StarlightRpcException(StarlightRpcException.INTERNAL_SERVER_ERROR, "Internal server error")); - } - - @Test - public void getRequest() { - BizWrapCallback bizWrapCallback = new BizWrapCallback(callback, request); - FilterCallback filterCallback = new FilterCallback(bizWrapCallback, new TestFilter(), request); - Assert.assertEquals(filterCallback.getRequest(), request); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallbackTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallbackTest.java deleted file mode 100644 index aa7ec8a5..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/callback/FutureCallbackTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.callback; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.ResultFuture; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class FutureCallbackTest { - - private Request request; - - private Response response; - - private Timeout timeout; - - @Before - public void before() { - timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - System.out.println("Timeout"); - } - }, 3, TimeUnit.SECONDS); - - request = new RpcRequest(); - response = new RpcResponse(); - response.setStatus(Constants.SUCCESS_CODE); - response.setResult("Test"); - } - - @Test - public void onResponse() throws ExecutionException, InterruptedException, TimeoutException { - ResultFuture resultFuture = new ResultFuture(); - FutureCallback futureCallback = new FutureCallback(resultFuture, request); - futureCallback.addTimeout(timeout); - futureCallback.onResponse(response); - Assert.assertEquals(resultFuture.get(), "Test"); - - ResultFuture resultFuture2 = new ResultFuture(); - FutureCallback futureCallback2 = new FutureCallback(resultFuture2, request); - futureCallback2.addTimeout(timeout); - futureCallback2.onResponse(response); - Assert.assertEquals(resultFuture.get(10, TimeUnit.MILLISECONDS), "Test"); - futureCallback2.onResponse(response); - } - - @Test - public void onError() throws ExecutionException, InterruptedException { - ResultFuture resultFuture = new ResultFuture(); - FutureCallback futureCallback = new FutureCallback(resultFuture, request); - futureCallback.addTimeout(timeout); - futureCallback - .onError(new StarlightRpcException(StarlightRpcException.INTERNAL_SERVER_ERROR, "Internal server error")); - try { - resultFuture.get(); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - Assert - .assertTrue(((StarlightRpcException) e).getCode().equals(StarlightRpcException.INTERNAL_SERVER_ERROR)); - } - - futureCallback.onError(new Exception()); - } - - @Test - public void getRequest() { - ResultFuture resultFuture = new ResultFuture(); - FutureCallback futureCallback = new FutureCallback(resultFuture, request); - Assert.assertEquals(futureCallback.getRequest(), request); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/AsyncTestService.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/AsyncTestService.java deleted file mode 100644 index f12821aa..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/AsyncTestService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.callback.Callback; - -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/3/24. - */ -public interface AsyncTestService extends TestService { - - Future echoFuture(String echo); - - void echoCallback(String echo, Callback callback); - - void testCallback(String echo, Callback callback); - - void test(String echo); - - void notAsyncCallback(String echo); - - String notAsyncCallback(String echo, Callback callback); - - String notAsyncFuture(String echo); -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactoryTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactoryTest.java deleted file mode 100644 index 3e806600..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JDKProxyFactoryTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.StarlightClient; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/24. - */ -public class JDKProxyFactoryTest { - - private JDKProxyFactory jdkProxyFactory; - - private StarlightClient starlightClient; - - @Before - public void before() { - jdkProxyFactory = new JDKProxyFactory(); - starlightClient = Mockito.mock(StarlightClient.class); - doNothing().when(starlightClient).request(any(), any()); - } - - @Test - public void getProxy() { - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setProtocol("brpc"); - TestService testService = jdkProxyFactory.getProxy(TestService.class, serviceConfig, starlightClient); - - Assert.assertFalse(testService.equals("test")); - Assert.assertEquals(testService.hashCode(), testService.hashCode()); - Assert.assertEquals(testService.toString(), testService.toString()); - AsyncTestService asyncTestService = - jdkProxyFactory.getProxy(AsyncTestService.class, serviceConfig, starlightClient); - asyncTestService.echoCallback("Hello", new Callback() { - @Override - public void onResponse(Object response) {} - - @Override - public void onError(Throwable e) {} - }); - try { - asyncTestService.testCallback("hello", new Callback() { - @Override - public void onResponse(Object response) {} - - @Override - public void onError(Throwable e) {} - }); - } catch (Exception e) { - Assert.assertTrue(e instanceof StarlightRpcException); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandlerTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandlerTest.java deleted file mode 100644 index 2bdb1dee..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/JdkInvocationHandlerTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import org.junit.Test; - -import java.lang.reflect.Method; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/3/31. - */ -public class JdkInvocationHandlerTest { - - private static final JdkInvocationHandler jdkHandler = new JdkInvocationHandler(AsyncTestService.class, null, null); - - @Test - public void targetMethod() throws NoSuchMethodException { - Method echoMethod = TestService.class.getMethod("echo", String.class); - assertEquals(echoMethod, jdkHandler.targetMethod(echoMethod)); - - Class targateClass = AsyncTestService.class; - - Method futureMethod = targateClass.getMethod("echoFuture", String.class); - Method method = jdkHandler.targetMethod(futureMethod); - assertNotEquals(futureMethod, method); - assertEquals(echoMethod, method); - - Method callBackMethod = targateClass.getMethod("echoCallback", String.class, Callback.class); - Method metho2 = jdkHandler.targetMethod(callBackMethod); - assertNotEquals(callBackMethod, metho2); - assertEquals(echoMethod, metho2); - - Method testCallback = targateClass.getMethod("testCallback", String.class, Callback.class); - try { - jdkHandler.targetMethod(testCallback); - } catch (Exception e) { - assertTrue(e instanceof StarlightRpcException); - } - - } - - @Test - public void targetServiceClass() { - assertEquals(jdkHandler.targetServiceClass(AsyncTestService.class), TestService.class); - assertEquals(jdkHandler.targetServiceClass(TestService.class), TestService.class); - } - - @Test - public void isAsyncCall() throws NoSuchMethodException { - // TestService - Method echoMethod = TestService.class.getMethod("echo", String.class); - assertFalse(jdkHandler.isAsyncCall(echoMethod)); - - Method notCallbackMethod = TestService.class.getMethod("notCallback", String.class); - assertFalse(jdkHandler.isAsyncCall(notCallbackMethod)); - - Method notCallback2Method = TestService.class.getMethod("notCallback2", String.class, Callback.class); - assertFalse(jdkHandler.isAsyncCall(notCallback2Method)); - - Method notFutureMethod = TestService.class.getMethod("notFuture", String.class); - assertFalse(jdkHandler.isAsyncCall(notFutureMethod)); - - Method notFuture2Method = TestService.class.getMethod("notFuture2", String.class); - assertFalse(jdkHandler.isAsyncCall(notFuture2Method)); - - // AsyncTestService - Method callbackMethod = AsyncTestService.class.getMethod("echoCallback", String.class, Callback.class); - assertTrue(jdkHandler.isAsyncCall(callbackMethod)); - - Method futureMethod = AsyncTestService.class.getMethod("echoFuture", String.class); - assertTrue(jdkHandler.isAsyncCall(futureMethod)); - - Method testCallbackMethod = AsyncTestService.class.getMethod("testCallback", String.class, Callback.class); - assertTrue(jdkHandler.isAsyncCall(testCallbackMethod)); - - Method testMethod = AsyncTestService.class.getMethod("test", String.class); - assertFalse(jdkHandler.isAsyncCall(testMethod)); - - Method notAsyncCallbackMethod = AsyncTestService.class.getMethod("notAsyncCallback", String.class); - assertFalse(jdkHandler.isAsyncCall(notAsyncCallbackMethod)); - - Method notAsyncCallbackMethod2 = - AsyncTestService.class.getMethod("notAsyncCallback", String.class, Callback.class); - assertFalse(jdkHandler.isAsyncCall(notAsyncCallbackMethod2)); - - Method notAsyncFutureMethod = AsyncTestService.class.getMethod("notAsyncFuture", String.class); - assertFalse(jdkHandler.isAsyncCall(notAsyncFutureMethod)); - - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/TestService.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/TestService.java deleted file mode 100644 index 4b2655b6..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/proxy/TestService.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.proxy; - -import com.baidu.cloud.starlight.api.rpc.callback.Callback; - -import java.util.concurrent.Future; - -/** - * Created by liuruisen on 2020/3/24. - */ -public interface TestService { - - String echo(String echo); - - String notCallback(String echo); - - void notFuture(String echo); - - void notCallback2(String echo, Callback callback); - - Future notFuture2(String echo); - -} diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactoryTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactoryTest.java deleted file mode 100644 index d7b497f7..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/rpc/threadpool/RpcThreadPoolFactoryTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.rpc.threadpool; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.core.integrate.service.UserService; -import com.baidu.cloud.starlight.core.integrate.service.UserServiceImpl; -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.ThreadPoolExecutor; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class RpcThreadPoolFactoryTest { - - private RpcThreadPoolFactory rpcThreadPoolFactory = new RpcThreadPoolFactory(Constants.DEFAULT_BIZ_THREAD_POOL_SIZE, - Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE, "r"); - - @Test - public void getThreadPool() { - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl()); - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setInvokeTimeoutMills(1000); - serviceConfig.setThreadPoolSize(1); - serviceConfig.setMaxThreadPoolSize(3); - serviceConfig.setIdleThreadKeepAliveSecond(3); - serviceConfig.setMaxRunnableQueueSize(100); - rpcService.setServiceConfig(serviceConfig); - ThreadPoolExecutor poolExecutor2 = rpcThreadPoolFactory.getThreadPool(rpcService); - Assert.assertTrue(poolExecutor2.getCorePoolSize() == 1); - Assert.assertTrue(poolExecutor2.getMaximumPoolSize() == 3); - } - - @Test - public void testGetThreadPool() { - ThreadPoolExecutor poolExecutor = rpcThreadPoolFactory.getThreadPool(); - Assert.assertEquals(Constants.DEFAULT_BIZ_THREAD_POOL_SIZE.intValue(), poolExecutor.getCorePoolSize()); - Assert.assertEquals(Constants.DEFAULT_MAX_BIZ_THREAD_POOL_SIZE.intValue(), poolExecutor.getMaximumPoolSize()); - } - - @Test - public void close() { - RpcService rpcService = new RpcService(UserService.class, new UserServiceImpl()); - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setInvokeTimeoutMills(1000); - serviceConfig.setThreadPoolSize(1); - serviceConfig.setMaxThreadPoolSize(3); - serviceConfig.setMaxRunnableQueueSize(100); - serviceConfig.setIdleThreadKeepAliveSecond(3); - rpcService.setServiceConfig(serviceConfig); - ThreadPoolExecutor executor = rpcThreadPoolFactory.getThreadPool(rpcService); - Assert.assertFalse(executor.isShutdown()); - rpcThreadPoolFactory.close(); - Assert.assertTrue(executor.isShutdown()); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStatsTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStatsTest.java deleted file mode 100644 index 5944429f..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/FixedTimeWindowStatsTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/25. - */ -public class FixedTimeWindowStatsTest { - - @Test - public void recordReqCount() { - FixedTimeWindowStats stats = new FixedTimeWindowStats(180); - - for (int i = 0; i < 500; i++) { - int finalI = i; - new Thread(() -> { - if (finalI < 200) { - stats.recordReqCount(true); - } else { - stats.recordReqCount(false); - } - }).start(); - } - - try { - TimeUnit.SECONDS.sleep(5); - } catch (InterruptedException e) { - // ignore - } - - System.out.println("ReqCount: " + stats.totalReqCount()); - System.out.println("FailCount: " + stats.failReqCount()); - System.out.println("SuccCount: " + stats.sucReqCount()); - assertEquals(300, stats.failReqCount().intValue()); - assertEquals(500, stats.totalReqCount().intValue()); - assertEquals(200, stats.sucReqCount().intValue()); - } - - @Test - public void recordReqCountExpire() { - FixedTimeWindowStats stats = new FixedTimeWindowStats(5); - - for (int i = 0; i < 500; i++) { - int finalI = i; - new Thread(() -> { - if (finalI < 200) { - stats.recordReqCount(true); - } else { - stats.recordReqCount(false); - } - }).start(); - } - - try { - TimeUnit.SECONDS.sleep(7); - } catch (InterruptedException e) { - // ignore - } - - System.out.println("ReqCount: " + stats.totalReqCount()); - System.out.println("FailCount: " + stats.failReqCount()); - System.out.println("SuccCount: " + stats.sucReqCount()); - assertEquals(0, stats.failReqCount().intValue()); - assertEquals(0, stats.totalReqCount().intValue()); - assertEquals(0, stats.sucReqCount().intValue()); - } - -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatisticsTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatisticsTest.java deleted file mode 100644 index 14c3e56a..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatisticsTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/25. - */ -public class StarlightStatisticsTest { - - private static final String TEST = "Test"; - - @Test - public void record() { - StarlightStatistics statistics = new StarlightStatistics(); - statistics.registerStats(TEST, new FixedTimeWindowStats(1000)); - Response response = new RpcResponse(); - statistics.record(new RpcRequest(), response); - assertTrue(statistics.discoverStats(TEST) instanceof FixedTimeWindowStats); - assertEquals(1, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).totalReqCount().intValue()); - assertEquals(0, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).failReqCount().intValue()); - - response.setStatus(1004); - statistics.record(new RpcRequest(), response); - assertEquals(2, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).totalReqCount().intValue()); - assertEquals(1, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).failReqCount().intValue()); - - response.setStatus(3001); - statistics.record(new RpcRequest(), response); - assertEquals(3, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).totalReqCount().intValue()); - assertEquals(1, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).failReqCount().intValue()); - - response.setStatus(2001); - statistics.record(new RpcRequest(), response); - assertEquals(4, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).totalReqCount().intValue()); - assertEquals(2, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).failReqCount().intValue()); - } - - @Test - public void recordMultiThread() { - StarlightStatistics statistics = new StarlightStatistics(); - for (int i = 0; i < 500; i++) { - new Thread(() -> { - statistics.registerStats(TEST, new FixedTimeWindowStats(100)); - statistics.record(new RpcRequest(), new RpcResponse()); - }).start(); - } - - try { - TimeUnit.SECONDS.sleep(5); - } catch (InterruptedException e) { - // ignore - } - - assertTrue(statistics.discoverStats(TEST) instanceof FixedTimeWindowStats); - assertEquals(500, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).totalReqCount().intValue()); - assertEquals(0, ((FixedTimeWindowStats) statistics.discoverStats(TEST)).failReqCount().intValue()); - } - - @Test - public void removeStats() { - StarlightStatistics statistics = new StarlightStatistics(); - statistics.registerStats(TEST, new FixedTimeWindowStats(100)); - assertNotNull(statistics.discoverStats(TEST)); - statistics.removeStats(TEST); - assertNull(statistics.discoverStats(TEST)); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManagerTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManagerTest.java deleted file mode 100644 index 8f7a154f..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/statistics/StarlightStatsManagerTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.statistics; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/4/25. - */ -public class StarlightStatsManagerTest { - - @Test - public void getOrCreateStats() { - URI uri = new URI("brpc", null, null, "localhost", 8080, null, null); - StarlightStatsManager.getOrCreateStats(uri); - assertNotNull(StarlightStatsManager.getStats(uri)); - } - - @Test - public void getOrCreateStatsMultiThread() { - URI uri = new URI("brpc", null, null, "localhost", 8080, null, null); - - for (int i = 0; i < 500; i++) { - new Thread(() -> { - StarlightStatsManager.getOrCreateStats(uri); - StarlightStatistics statistics = StarlightStatsManager.getStats(uri); - statistics.registerStats("TEST", new FixedTimeWindowStats(100)); - statistics.record(new RpcRequest(), new RpcResponse()); - }).start(); - } - try { - TimeUnit.SECONDS.sleep(5); - } catch (InterruptedException e) { - // ignore - } - StarlightStatistics statistics = StarlightStatsManager.getStats(uri); - assertNotNull(statistics); - assertTrue(statistics.discoverStats("TEST") instanceof FixedTimeWindowStats); - assertEquals(500, ((FixedTimeWindowStats) statistics.discoverStats("TEST")).totalReqCount().intValue()); - } - - @Test(expected = IllegalArgumentException.class) - public void getOrCreateStatsError() { - StarlightStatsManager.getOrCreateStats(null); - } - - @Test(expected = IllegalArgumentException.class) - public void getOrCreateStatsErrorEmpty() { - URI uri = new URI("brpc", null, null, null, -1, null, null); - StarlightStatsManager.getOrCreateStats(uri); - } - - @Test - public void removeStats() { - URI uri = new URI("brpc", null, null, "localhost", 8080, null, null); - StarlightStatsManager.getOrCreateStats(uri); - assertNotNull(StarlightStatsManager.getStats(uri)); - - StarlightStatsManager.removeStats(uri); - assertNull(StarlightStatsManager.getStats(uri)); - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtilsTest.java b/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtilsTest.java deleted file mode 100644 index ffee820d..00000000 --- a/starlight/starlight-core/src/test/java/com/baidu/cloud/starlight/core/utils/PojoJsonUtilsTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.core.utils; - -import com.baidu.cloud.starlight.core.integrate.model.ExtInfo; -import com.baidu.cloud.starlight.core.integrate.model.User; -import com.baidu.cloud.thirdparty.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2021/3/16. - */ -public class PojoJsonUtilsTest { - - @Test - public void realize() throws Exception { - - String pattern = "yyyy-MM-dd HH:mm:ss"; - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); - String date = simpleDateFormat.format(new Date()); - - Map genericTest = new HashMap<>(); - genericTest.put("date", date); - Object[] objects = PojoJsonUtils.realize(new Object[] {genericTest}, new Type[] {GenericTest.class}); - - assertNotNull(objects); - assertEquals(date, simpleDateFormat.format(((GenericTest) objects[0]).getDate())); - - long dateTime = new Date().getTime(); - Map genericTest2 = new HashMap<>(); - genericTest2.put("date", dateTime); - - Object[] objects2 = PojoJsonUtils.realize(new Object[] {genericTest2}, new Type[] {GenericTest.class}); - assertNotNull(objects2); - assertEquals(dateTime, ((GenericTest) objects2[0]).getDate().getTime()); - } - - @Test - public void realizeGeneric() { - - Map extInf = new HashMap<>(); - extInf.put("key", "asdhjashdkjas"); - extInf.put("value", "123123"); - - Map extInf2 = new HashMap<>(); - extInf2.put("key", "123123123"); - extInf2.put("value", 45678); - - List> extInfos = new ArrayList<>(); - extInfos.add(extInf); - extInfos.add(extInf2); - - try { - Method method = this.getClass().getMethod("genericMethod", Long.class, String.class, List.class); - Type[] paramTypes = method.getGenericParameterTypes(); - - String name = new ObjectMapper().writeValueAsString(new ExtInfo("key", "value")); - Object[] args = PojoJsonUtils.realize(new Object[] {1L, name, extInfos}, paramTypes); - - for (Object arg : args) { - System.out.println(arg); - } - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - public User genericMethod(Long id, String name, List extInfos) { - return new User(); - } - - @Test - public void generalize() throws Exception { - GenericTest genericTest = new GenericTest(); - genericTest.setDate(new Date()); - - Object result = PojoJsonUtils.generalize(genericTest); - assertTrue(result instanceof Map); - } - - public static class GenericTest { - private Date date; - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - } -} \ No newline at end of file diff --git a/starlight/starlight-core/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter b/starlight/starlight-core/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter deleted file mode 100644 index 75a8b925..00000000 --- a/starlight/starlight-core/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.filter.Filter +++ /dev/null @@ -1,2 +0,0 @@ -com.baidu.cloud.starlight.core.filter.TestFilter -com.baidu.cloud.starlight.core.filter.TestSameFilter \ No newline at end of file diff --git a/starlight/starlight-protocol/pom.xml b/starlight/starlight-protocol/pom.xml deleted file mode 100644 index c96722f3..00000000 --- a/starlight/starlight-protocol/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-protocol - pom - - - starlight-protocol-stargate - starlight-protocol-brpc - starlight-protocol-http - - - true - - - - com.baidu.cloud - starlight-serialization - ${project.version} - - - - org.powermock - powermock-module-junit4 - test - - - - org.powermock - powermock-api-mockito2 - test - - - - - diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/pom.xml b/starlight/starlight-protocol/starlight-protocol-brpc/pom.xml deleted file mode 100644 index a2488356..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/pom.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight-protocol - 2025.0.1-SNAPSHOT - - - starlight-protocol-brpc - - diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoder.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoder.java deleted file mode 100644 index 1d3efbf1..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoder.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.model.Wrapper; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.utils.ByteArrayUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.serialization.serializer.ProtobufSerializer; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.starlight.serialization.serializer.ProtoStuffSerializer; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * Created by liuruisen on 2020/2/6. - */ -public class BrpcDecoder implements ProtocolDecoder { - - @Override - public MsgBase decode(DynamicCompositeByteBuf input) throws CodecException { - - // not enough data - if (input.readableBytes() < BrpcProtocol.FIXED_LEN) { // not enough data - throw new CodecException(CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION, - "Too little data to parse using Brpc"); // wait and retry - } - - ByteBuf fixHeaderBuf = input.retainedSlice(BrpcProtocol.FIXED_LEN); - ByteBuf metaBuf = null; - ByteBuf dataBuf = null; - try { - byte[] magic = new byte[4]; - fixHeaderBuf.readBytes(magic); - if (!Arrays.equals(magic, BrpcProtocol.MAGIC_HEAD)) { // not match - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Magic num dose not match Brpc"); - } - - // the whole body size = meta data size + body data size - int bodySize = fixHeaderBuf.readInt(); - if (input.readableBytes() < BrpcProtocol.FIXED_LEN + bodySize) { - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTENOUGHDATA_EXCEPTION, - "Data not enough to parse using Brpc"); // wait and retry - } - // 512M - if (bodySize > BrpcProtocol.MAX_BODY_SIZE) { - throw new CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - "Data size is bigger than max_body_size(512M), the size is " + bodySize); // failed - } - - // meta data size - int metaSize = fixHeaderBuf.readInt(); - - input.skipBytes(BrpcProtocol.FIXED_LEN); // skip head - - metaBuf = input.readRetainedSlice(metaSize); - - // decode meta data in IO Thread - MsgBase output = decodeMeta(metaBuf); - - // body data size - int dataSize = bodySize - metaSize; - if (dataSize > 0) { - dataBuf = input.readRetainedSlice(dataSize); - if (dataBuf == null || dataBuf.readableBytes() == 0) { - throw new CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - "Brpc decode failed, brpc body data is null"); - } - // data body: body data + binary attach data, remember to release - byte[] dataBytes = new byte[dataSize]; // data - dataBuf.readBytes(dataBytes); - output.setBodyBytes(dataBytes); - } - // set protocol name - output.setProtocolName(BrpcProtocol.PROTOCOL_NAME); - - return output; - } finally { - fixHeaderBuf.release(); - if (metaBuf != null) { - metaBuf.release(); - } - if (dataBuf != null) { - dataBuf.release(); - } - } - } - - private MsgBase decodeMeta(ByteBuf metaBuf) throws CodecException { - if (metaBuf == null || metaBuf.readableBytes() == 0) { - throw new CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - "Brpc decode failed, brpc meta data is null"); - } - MsgBase msgBase = null; - try { - final int brpcMetaLength = metaBuf.readableBytes(); - byte[] brpcMetaArray = new byte[brpcMetaLength]; - metaBuf.readBytes(brpcMetaArray, 0, brpcMetaLength); - - ProtoStuffSerializer serializer = - (ProtoStuffSerializer) serializer(BrpcProtocol.SERIALIZER_TYPE_PROTOSTUFF); - BrpcMeta rpcMeta = - (BrpcMeta) serializer.deserialize(brpcMetaArray, BrpcMeta.class, BrpcProtocol.metaStrategyFlag(null)); - - if (rpcMeta != null) { - if (rpcMeta.getRequest() != null && !StringUtils.isEmpty(rpcMeta.getRequest().getServiceName())) { - msgBase = requestMeta(rpcMeta); - } - - if (rpcMeta.getResponse() != null && rpcMeta.getResponse().getErrorCode() != null) { - msgBase = responseMeta(rpcMeta); - } - - // attachment size 及其 binary attachment何种场景下使用? - if (rpcMeta.getAttachmentSize() != null && rpcMeta.getAttachmentSize() > 0 && msgBase != null) { - if (msgBase.getAttachmentKv() == null) { - Map kvMap = new HashMap<>(); - msgBase.setAttachmentKv(kvMap); - } - msgBase.getAttachmentKv().put(BrpcProtocol.BINARY_ATTACH_SIZE_KEY, rpcMeta.getAttachmentSize()); - } - } - } catch (Exception e) { - throw new CodecException("Brpc decode metaBuf failed, deserialize meta error", e); - } - - return msgBase; - } - - private Request requestMeta(BrpcMeta rpcMeta) { - Request request = new RpcRequest(rpcMeta.getCorrelationId()); - // msgBase common information - request.setCompressType(rpcMeta.getCompressType()); - request.setHeartbeat(false); // not support heartbeat message - // protocol - request.setProtocolName(BrpcProtocol.PROTOCOL_NAME); - - // TODO Streaming模式尚未使用 - - // Request information - BrpcRequestMeta requestMeta = rpcMeta.getRequest(); - request.setServiceName(requestMeta.getServiceName()); - request.setMethodName(requestMeta.getMethodName()); - - // attachmentKv - Map kvMap = new HashMap<>(); - - // auth data - if (rpcMeta.getAuthenticationData() != null && rpcMeta.getAuthenticationData().length > 0) { - kvMap.put(BrpcProtocol.AUTH_KEY, new String(rpcMeta.getAuthenticationData())); - } - - // requestId - kvMap.put(Constants.REQUEST_ID_KEY, requestMeta.getLogId()); - // trace - kvMap.put(Constants.TRACE_ID_KEY, requestMeta.getTraceId()); - kvMap.put(Constants.SPAN_ID_KEY, requestMeta.getSpanId()); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, requestMeta.getParentSpanId()); - // kv attach - if (requestMeta.getExtFields() != null && requestMeta.getExtFields().size() > 0) { - for (BrpcRequestMeta.BrpcRequestMetaExt extField : requestMeta.getExtFields()) { - kvMap.put(extField.getKey(), extField.getValue()); - } - } - // 兼容java传输Object类型的attachKv场景,全量attachKv由starlight request ext与brpc request ext组成 - if (requestMeta.getStarlightRequestMeta() != null - && requestMeta.getStarlightRequestMeta().getStarlightExtFields() != null) { - kvMap.putAll(requestMeta.getStarlightRequestMeta().getStarlightExtFields()); - } - request.setAttachmentKv(kvMap); - - return request; - } - - private Response responseMeta(BrpcMeta rpcMeta) { - Response response = new RpcResponse(rpcMeta.getCorrelationId()); - // msgBase common information - response.setCompressType(rpcMeta.getCompressType()); - - // Response information - BrpcResponseMeta responseMeta = rpcMeta.getResponse(); - response.setStatus(CodeMapping.getStarlightMappingOfBrpcNo(responseMeta.getErrorCode())); - response.setErrorMsg(responseMeta.getErrorText()); - - // attachmentKv - Map kvMap = new HashMap<>(); - kvMap.put(Constants.PROTOCOL_KEY, BrpcProtocol.PROTOCOL_NAME); - response.setAttachmentKv(kvMap); - // starlight response meta - if (responseMeta.getStarlightResponseMeta() != null) { - kvMap.putAll(responseMeta.getStarlightResponseMeta().getStarlightExtFields()); - } - - return response; - } - - @Override - public void decodeBody(MsgBase msgBase) throws CodecException { - if (msgBase == null) { - throw new CodecException(CodecException.BODY_DECODE_EXCEPTION, "Message is null to decode"); - } - if (msgBase.getBodyBytes() == null || msgBase.getBodyBytes().length == 0) { // body is null, return - return; - } - - int attachSize = 0; // binary attach - if (msgBase.getAttachmentKv() != null - && msgBase.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY) != null) { - attachSize = (int) msgBase.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - if (attachSize > 0) { - byte[] dataBytes = - ByteArrayUtils.subByte(msgBase.getBodyBytes(), 0, msgBase.getBodyBytes().length - attachSize); - byte[] attach = ByteArrayUtils.subByte(msgBase.getBodyBytes(), - msgBase.getBodyBytes().length - attachSize, attachSize); - msgBase.setBodyBytes(dataBytes); - msgBase.getAttachmentKv().put(BrpcProtocol.BINARY_ATTACH_KEY, attach); - } - } - - if (msgBase instanceof Request) { - decodeRequestBody((Request) msgBase); - } - if (msgBase instanceof Response) { - decodeResponseBody((Response) msgBase); - } - } - - private void decodeRequestBody(Request request) { - Class[] originParamTypes = request.getParamsTypes(); - - // Compatible with various problems in the Java scene - BrpcProtocol.wrapReqParams(request); - - Serializer serializer = serializer(BrpcProtocol.bodySerType(request)); - - Object object = null; - if (serializer instanceof ProtoStuffSerializer) { - ProtoStuffSerializer stuffSerializer = (ProtoStuffSerializer) serializer; - // compatible empty collection in response body - Integer idStrategyFlag = BrpcProtocol.bodyStrategyFlag(BrpcProtocol.bodySerMode(request)); - object = stuffSerializer.deserialize(request.getBodyBytes(), request.getParamsTypes()[0], idStrategyFlag); - } - - if (serializer instanceof ProtobufSerializer) { - ProtobufSerializer protobufSerializer = (ProtobufSerializer) serializer; - object = protobufSerializer.deserialize(request.getBodyBytes(), request.getParamsTypes()[0]); - } - request.setParams(new Object[] {object}); - - // revert wrap - if (object instanceof Wrapper) { // multi params or generic call - request.setParams((Object[]) ((Wrapper) object).getObj()); - } - - // revert wrap - request.setParamsTypes(originParamTypes); - } - - private void decodeResponseBody(Response response) { - Class originRetType = response.getReturnType(); - - // Compatible with various problems in the Java scene - BrpcProtocol.wrapRespResult(response); - - Serializer serializer = serializer(BrpcProtocol.bodySerType(response.getRequest())); - - Object result = null; - if (serializer instanceof ProtoStuffSerializer) { - ProtoStuffSerializer stuffSerializer = (ProtoStuffSerializer) serializer; - // compatible empty collection in response body - Integer idStrategyFlag = BrpcProtocol.bodyStrategyFlag(BrpcProtocol.bodySerMode(response.getRequest())); - result = stuffSerializer.deserialize(response.getBodyBytes(), response.getReturnType(), idStrategyFlag); - } - - if (serializer instanceof ProtobufSerializer) { - ProtobufSerializer protobufSerializer = (ProtobufSerializer) serializer; - result = protobufSerializer.deserialize(response.getBodyBytes(), response.getReturnType()); - } - response.setResult(result); - - if (result instanceof Wrapper) { - Wrapper wrapper = (Wrapper) result; - response.setResult(wrapper.getObj()); - } - - // revert wrap - response.setReturnType(originRetType); - } - - private Serializer serializer(String serializerType) { - BrpcProtocol brpcProtocol = - (BrpcProtocol) ExtensionLoader.getInstance(Protocol.class).getExtension(BrpcProtocol.PROTOCOL_NAME); - return brpcProtocol.getSerialize(serializerType); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoder.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoder.java deleted file mode 100644 index d85a3888..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoder.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.utils.ByteArrayUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.serialization.serializer.ProtobufSerializer; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.starlight.serialization.serializer.ProtoStuffSerializer; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static com.baidu.cloud.starlight.protocol.brpc.BrpcProtocol.FIXED_LEN; - -/** - * Created by liuruisen on 2020/2/6. - */ -public class BrpcEncoder implements ProtocolEncoder { - - @Override - public ByteBuf encode(MsgBase input) throws CodecException { - if (input == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, "MsgBase is null, cannot encode"); - } - - if (input instanceof Request) { - return encodeRequest((Request) input); - } - - if (input instanceof Response) { - return encodeResponse((Response) input); - } - - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "MsgBase type is illegal {" + input.getClass().getName() + "}, cannot encode"); - } - - private ByteBuf encodeRequest(Request request) { - try { - // request body: meta - // BaiduRpcProto.RpcRequestMeta.Builder requestMeta = BaiduRpcProto.RpcRequestMeta.newBuilder(); - BrpcRequestMeta requestMeta = new BrpcRequestMeta(); - requestMeta.setLogId(request.getId()); - // serviceId(cross-language) or interfaceName(only java) - requestMeta.setServiceName(request.getServiceName()); - requestMeta.setMethodName(request.getMethodName()); - - // requestMeta - if (request.getAttachmentKv() != null) { - Map requestAttachKv = new HashMap<>(request.getAttachmentKv()); - - // auth key and binary attach size key will be set to RpcMeta, remove to prevent repeated addition - requestAttachKv.remove(BrpcProtocol.AUTH_KEY); - requestAttachKv.remove(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - requestAttachKv.remove(BrpcProtocol.BINARY_ATTACH_KEY); - - // trace id, span id, parent span id - Object traceId = requestAttachKv.remove(Constants.TRACE_ID_KEY); - if (traceId instanceof Long) { - requestMeta.setTraceId((Long) traceId); - } - - Object spanId = requestAttachKv.remove(Constants.SPAN_ID_KEY); - if (spanId instanceof Long) { - requestMeta.setSpanId((Long) spanId); - } - - Object parentSpanId = requestAttachKv.remove(Constants.PARENT_SPAN_ID_KEY); - if (parentSpanId instanceof Long) { - requestMeta.setParentSpanId((Long) parentSpanId); - } - - // requestMeta ext map - Map requestAttachKv2 = new HashMap<>(requestAttachKv); - - List metaExtList = new LinkedList<>(); - for (Map.Entry kv : requestAttachKv.entrySet()) { - if (kv.getKey() != null && kv.getValue() != null && kv.getValue() instanceof String) { - BrpcRequestMeta.BrpcRequestMetaExt metaExt = new BrpcRequestMeta.BrpcRequestMetaExt(); - metaExt.setKey(kv.getKey()); - metaExt.setValue((String) kv.getValue()); - metaExtList.add(metaExt); - - requestAttachKv2.remove(kv.getKey()); // remove to prevent repeated addition - } - } - requestMeta.setExtFields(metaExtList); - - // starlight request meta - if (requestAttachKv2.size() > 0) { - StarlightRequestMeta starlightRequestMeta = new StarlightRequestMeta(); - starlightRequestMeta.setStarlightExtFields(requestAttachKv2); - - requestMeta.setStarlightRequestMeta(starlightRequestMeta); - } - } - - // rpc meta - BrpcMeta meta = new BrpcMeta(); - meta.setCorrelationId(request.getId()); - meta.setCompressType(request.getCompressType()); - meta.setRequest(requestMeta); - - if (request.getAttachmentKv() != null) { - // auth data - Object authObject = request.getAttachmentKv().get(BrpcProtocol.AUTH_KEY); - if (authObject instanceof String) { - String authData = (String) authObject; - meta.setAuthenticationData(authData.getBytes()); - } - - // binaryAttachment - Object binarySizeObject = request.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - if (binarySizeObject instanceof Integer) { - Integer binaryAttachmentSize = (Integer) binarySizeObject; - meta.setAttachmentSize(binaryAttachmentSize); - } - } - - Integer idStrategyFlag = BrpcProtocol.metaStrategyFlag(BrpcProtocol.bodySerMode(request)); - - // request body: data - // data had been serialize and compress in Work Thread: data + binary attach - ProtoStuffSerializer serializer = - (ProtoStuffSerializer) serializer(BrpcProtocol.SERIALIZER_TYPE_PROTOSTUFF); - return protocolEncode(serializer.serialize(meta, BrpcMeta.class, idStrategyFlag), request.getBodyBytes()); - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, "Use brpc encode request failed!", e); - } - } - - private ByteBuf encodeResponse(Response response) { - // rpc meta - BrpcMeta meta = new BrpcMeta(); - meta.setCorrelationId(response.getId()); - meta.setCompressType(response.getCompressType()); - - // response meta - BrpcResponseMeta responseMeta = new BrpcResponseMeta(); - responseMeta.setErrorCode(CodeMapping.getBrpcMappingOfStarlightNo(response.getStatus())); - if (response.getErrorMsg() != null) { - responseMeta.setErrorText(response.getErrorMsg()); - } - // starlight response meta contains - responseMeta.setStarlightResponseMeta(generateStarlightRespMeta(response)); - - meta.setResponse(responseMeta); - - if (response.getAttachmentKv() != null) { - // binaryAttachment - Object binarySizeObject = response.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - if (binarySizeObject instanceof Integer) { - Integer binaryAttachmentSize = (Integer) binarySizeObject; - meta.setAttachmentSize(binaryAttachmentSize); - } - } - - Integer idStrategyFlag = BrpcProtocol.metaStrategyFlag(BrpcProtocol.bodySerMode(response.getRequest())); - - ProtoStuffSerializer serializer = (ProtoStuffSerializer) serializer(BrpcProtocol.SERIALIZER_TYPE_PROTOSTUFF); - // data had been serialize and compress in Work Thread: data + binary attach - return protocolEncode(serializer.serialize(meta, BrpcMeta.class, idStrategyFlag), response.getBodyBytes()); - } - - /** - * Starlight brpc特有的Response meta信息,比如用于日志记录的server端执行耗时情况 - * - * @param response - * @return - */ - private StarlightResponseMeta generateStarlightRespMeta(Response response) { - addAdditionalRespKv(response); - StarlightResponseMeta starlightResponseMeta = new StarlightResponseMeta(); - starlightResponseMeta.setStarlightExtFields(response.getAttachmentKv()); - return starlightResponseMeta; - } - - private ByteBuf protocolEncode(byte[] metaBytes, byte[] dataBytes) { - // header buf - ByteBuf headerBuf = Unpooled.buffer(FIXED_LEN); - // magic num - headerBuf.writeBytes(BrpcProtocol.MAGIC_HEAD); - int bodySize = metaBytes.length; - if (dataBytes != null && dataBytes.length > 0) { - bodySize = bodySize + dataBytes.length; - } - // body size - headerBuf.writeInt(bodySize); - // meta size - headerBuf.writeInt(metaBytes.length); - - // body buf - ByteBuf bodyBuf = null; - // body - if (dataBytes != null && dataBytes.length > 0) { - bodyBuf = Unpooled.wrappedBuffer(metaBytes, dataBytes); - } else { - bodyBuf = Unpooled.wrappedBuffer(metaBytes); - } - - return Unpooled.wrappedBuffer(headerBuf, bodyBuf); - } - - @Override - public void encodeBody(MsgBase msgBase) throws CodecException { - if (msgBase == null) { - throw new CodecException(CodecException.BODY_ENCODE_EXCEPTION, "MsgBase is null, cannot encode"); - } - - if (msgBase instanceof Request) { - encodeRequestBody((Request) msgBase); - } - - if (msgBase instanceof Response) { - encodeResponseBody((Response) msgBase); - } - - // support brpc attachment bytes - if (msgBase.getAttachmentKv() != null - && msgBase.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_KEY) != null) { - byte[] attachBinary = (byte[]) msgBase.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_KEY); - msgBase.getAttachmentKv().put(BrpcProtocol.BINARY_ATTACH_SIZE_KEY, attachBinary.length); - - byte[] bodyBytes = ByteArrayUtils.byteMerger(msgBase.getBodyBytes(), attachBinary); - msgBase.setBodyBytes(bodyBytes); - } - } - - private void encodeRequestBody(Request request) throws CodecException { - // add serialize strategy to attachment kv - if (request.getServiceConfig() != null && !StringUtils.isEmpty(request.getServiceConfig().getSerializeMode())) { - request.getAttachmentKv().put(Constants.SERIALIZER_MODE_KEY, request.getServiceConfig().getSerializeMode()); - } - - if (request.getParams() == null || request.getParams().length == 0) { // no body data - return; - } - - Class[] originParamTypes = request.getParamsTypes(); - Object[] originParams = request.getParams(); - - // Compatible with various problems in the Java scene - BrpcProtocol.wrapReqParams(request); - - Serializer serializer = serializer(BrpcProtocol.bodySerType(request)); - byte[] bodyBytes = null; - if (serializer instanceof ProtoStuffSerializer) { - ProtoStuffSerializer protoStuffSer = (ProtoStuffSerializer) serializer; - Integer idStrategyFlag = BrpcProtocol.bodyStrategyFlag(BrpcProtocol.bodySerMode(request)); - bodyBytes = protoStuffSer.serialize(request.getParams()[0], request.getParamsTypes()[0], idStrategyFlag); - } - - if (serializer instanceof ProtobufSerializer) { - bodyBytes = serializer.serialize(request.getParams()[0], request.getParamsTypes()[0]); - } - - request.setBodyBytes(bodyBytes); - - // revert wrap - request.setParams(originParams); - request.setParamsTypes(originParamTypes); - } - - private void encodeResponseBody(Response response) throws CodecException { - // no body data, the scene of the call error has been handled in #encodeResponse - if (response.getResult() == null) { - return; - } - - Object originRet = response.getResult(); - Class originRetType = response.getReturnType(); - - // Compatible with various problems in the Java scene - BrpcProtocol.wrapRespResult(response); - - Serializer serializer = serializer(BrpcProtocol.bodySerType(response.getRequest())); - byte[] bodyBytes = null; - if (serializer instanceof ProtoStuffSerializer) { - Integer idStrategyFlag = BrpcProtocol.bodyStrategyFlag(BrpcProtocol.bodySerMode(response.getRequest())); - ProtoStuffSerializer stuffSerializer = (ProtoStuffSerializer) serializer; - bodyBytes = stuffSerializer.serialize(response.getResult(), response.getReturnType(), idStrategyFlag); - } - - if (serializer instanceof ProtobufSerializer) { - ProtobufSerializer protobufSerializer = (ProtobufSerializer) serializer; - bodyBytes = protobufSerializer.serialize(response.getResult(), response.getReturnType()); - } - - response.setBodyBytes(bodyBytes); - - response.setResult(originRet); - response.setReturnType(originRetType); - } - - private Serializer serializer(String serializerType) { - BrpcProtocol brpcProtocol = - (BrpcProtocol) ExtensionLoader.getInstance(Protocol.class).getExtension(BrpcProtocol.PROTOCOL_NAME); - return brpcProtocol.getSerialize(serializerType); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcMeta.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcMeta.java deleted file mode 100644 index 6f2f0471..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcMeta.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -/** - * Created by liuruisen on 2020/8/27. - */ -public class BrpcMeta { - - /** - * message RpcMeta { optional RpcRequestMeta request = 1; optional RpcResponseMeta response = 2; optional Integer32 - * compress_type = 3; optional Integer64 correlation_id = 4; optional Integer32 attachment_size = 5; optional - * ChunkInfo chunk_info = 6; optional bytes authentication_data = 7; optional StreamSettings stream_settings = 8; } - */ - - private BrpcRequestMeta request; - - private BrpcResponseMeta response; - - private Integer compressType; - - private Long correlationId; - - private Integer attachmentSize; - - private BrpcChunkInfo chunkInfo; - - private byte[] authenticationData; - - private BrpcStreamSettings streamSettings; - - public BrpcRequestMeta getRequest() { - return request; - } - - public void setRequest(BrpcRequestMeta request) { - this.request = request; - } - - public BrpcResponseMeta getResponse() { - return response; - } - - public void setResponse(BrpcResponseMeta response) { - this.response = response; - } - - public Integer getCompressType() { - return compressType; - } - - public void setCompressType(Integer compressType) { - this.compressType = compressType; - } - - public Long getCorrelationId() { - return correlationId; - } - - public void setCorrelationId(Long correlationId) { - this.correlationId = correlationId; - } - - public Integer getAttachmentSize() { - return attachmentSize; - } - - public void setAttachmentSize(Integer attachmentSize) { - this.attachmentSize = attachmentSize; - } - - public BrpcChunkInfo getChunkInfo() { - return chunkInfo; - } - - public void setChunkInfo(BrpcChunkInfo chunkInfo) { - this.chunkInfo = chunkInfo; - } - - public byte[] getAuthenticationData() { - return authenticationData; - } - - public void setAuthenticationData(byte[] authenticationData) { - this.authenticationData = authenticationData; - } - - public BrpcStreamSettings getStreamSettings() { - return streamSettings; - } - - public void setStreamSettings(BrpcStreamSettings streamSettings) { - this.streamSettings = streamSettings; - } - - public static final class BrpcChunkInfo { - - /** - * message ChunkInfo { required Integer64 stream_id = 1; required Integer64 chunk_id = 2; } - */ - - private Long streamId; - - private Long chunkId; - - public Long getStreamId() { - return streamId; - } - - public void setStreamId(Long streamId) { - this.streamId = streamId; - } - - public Long getChunkId() { - return chunkId; - } - - public void setChunkId(Long chunkId) { - this.chunkId = chunkId; - } - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocol.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocol.java deleted file mode 100644 index 882fdc73..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocol.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.Wrapper; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.serialization.serializer.ProtobufSerializer; -import com.baidu.cloud.thirdparty.protostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.IdStrategy; -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.serialization.serializer.ProtoStuffSerializer; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.google.protobuf.MessageLite; - -import java.util.Collection; -import java.util.Map; - -/** - * Brpc Standard Protocol SPI name: brpc Created by liuruisen on 2020/2/6. - */ -public class BrpcProtocol implements Protocol { - - public static final String SERIALIZER_TYPE_PROTOSTUFF = "protostuff"; - - public static final String SERIALIZER_TYPE_PROTOBUF = "protobuf"; - - /** - * BRPC auth data key - */ - protected static final String AUTH_KEY = "auth_data"; - - /** - * Protocol name : brpc - */ - public static final String PROTOCOL_NAME = "brpc"; - - /** - * Brpc binary attachment size key: Brpc binary attachment will be stored in attachmentKv - */ - protected static final String BINARY_ATTACH_SIZE_KEY = "binary_attachment_size"; - - /** - * Brpc binary attachment key - */ - protected static final String BINARY_ATTACH_KEY = "binary_attachment"; - - /** - * Fixed length - */ - protected static final int FIXED_LEN = 12; - protected static final byte[] MAGIC_HEAD = "PRPC".getBytes(); - - /** - * MAX body size 512M - */ - protected static final Integer MAX_BODY_SIZE = 512 * 1024 * 1024; - - /** - * stargate protostuff IdStrategy - */ - protected static final IdStrategy IDSTRATEGY; - - private static final ProtocolEncoder ENCODER = new BrpcEncoder(); - - private static final ProtocolDecoder DECODER = new BrpcDecoder(); - - private static final Serializer PROTO_STUFF_SERIALIZER = new ProtoStuffSerializer(); - - private static final Serializer PROTOBUF_SERIALIZER = new ProtobufSerializer(); - - static { - /** - * Stargate will specify the following protostuff configuration when serializing and deserializing. But these - * configuration is not suitable for Brpc serialize/deserialize and these configurations will form flags for - * building IdStrategy, so we directly generate flags to construct IdStragety - * - * Stargate configuration: System.setProperty("protostuff.runtime.collection_schema_on_repeated_fields", - * "true"); System.setProperty("protostuff.runtime.morph_collection_interfaces", "true"); - * System.setProperty("protostuff.runtime.morph_map_interfaces", "true"); - * - */ - int flags = 0; - flags |= IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES; // enable by default - - IDSTRATEGY = new DefaultIdStrategy(flags); - } - - @Override - public ProtocolEncoder getEncoder() { - return ENCODER; - } - - @Override - public ProtocolDecoder getDecoder() { - return DECODER; - } - - @Override - public HeartbeatTrigger getHeartbeatTrigger() { - return null; // not support - } - - @Override - public Serializer getSerialize() { - // 默认选择protostuff - return getSerialize(SERIALIZER_TYPE_PROTOSTUFF); - } - - public Serializer getSerialize(String serializerType) { - // 选择protobuf作为序列化反序列化器 - if (SERIALIZER_TYPE_PROTOBUF.equalsIgnoreCase(serializerType)) { - return PROTOBUF_SERIALIZER; - } - // 其余一律选择protostuff - return PROTO_STUFF_SERIALIZER; - } - - /** - * Get serializeStrategyFlag by strategyType - * - * @param strategyType - * @return - */ - public static Integer bodyStrategyFlag(String strategyType) { - /** - * Stargate will specify the following protostuff configuration when serializing and deserializing. But these - * configuration is not suitable for Brpc serialize/deserialize and these configurations will form flags for - * building IdStrategy, so we directly generate flags to construct IdStragety - * - * Stargate configuration: System.setProperty("protostuff.runtime.collection_schema_on_repeated_fields", - * "true"); System.setProperty("protostuff.runtime.morph_collection_interfaces", "true"); - * System.setProperty("protostuff.runtime.morph_map_interfaces", "true"); - * - */ - int flags = 0; - flags |= IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES; // enable by default - - if (StringUtils.isEmpty(strategyType)) { - return flags; - } - - if (strategyType.equals(Constants.PROTO2_STD_MODE)) { - return flags; - } - - if (strategyType.equals(Constants.PROTO2_JAVA_MODE)) { - flags |= IdStrategy.PRESERVE_NULL_ELEMENTS; - return flags; - } - - return flags; - } - - /** - * Get serializeStrategyFlag by strategyType - * - * @param strategyType - * @return - */ - public static Integer metaStrategyFlag(String strategyType) { - int flags = 0; - flags |= IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES; // enable by default - return flags; - } - - public static String bodySerMode(Request request) { - // brpc协议交互时兼容emptylist - String serializeMode = null; - if (request.getServiceConfig() != null && request.getServiceConfig().getSerializeMode() != null) { - return request.getServiceConfig().getSerializeMode(); - } - // 适用response场景 - if (request.getAttachmentKv() != null) { - Object serMode = request.getAttachmentKv().get(Constants.SERIALIZER_MODE_KEY); - if (serMode instanceof String) { - serializeMode = (String) serMode; - } - } - return serializeMode; - } - - /** - * Support both protobuf-java and protostuff - * - * @param request - * @return - */ - public static String bodySerType(Request request) { - - // 兼容非Starlight的客户端调用starlight场景,此时附加信息中无serializerType信息 - if (request.getParamsTypes() != null && request.getParamsTypes().length == 1 - && MessageLite.class.isAssignableFrom(request.getParamsTypes()[0])) { - return SERIALIZER_TYPE_PROTOBUF; - } - - // 使用于跨语言、跨框架交互场景 - if (request.getReturnType() != null && MessageLite.class.isAssignableFrom(request.getReturnType())) { - return SERIALIZER_TYPE_PROTOBUF; - } - return SERIALIZER_TYPE_PROTOSTUFF; - } - - /** - * 兼容Brpc协议在落地时的各种兼容问题 - * - * @param request - */ - public static void wrapReqParams(Request request) { - // serializeMode is pb2-java - String serializeMode = BrpcProtocol.bodySerMode(request); - if (!StringUtils.isEmpty(serializeMode) && serializeMode.equalsIgnoreCase(Constants.PROTO2_JAVA_MODE)) { - request.setParams(new Object[] {new Wrapper(request.getParams())}); - request.setParamsTypes(new Class[] {Wrapper.class}); - return; - } - - // generic request - if (GenericUtil.isGenericMsg(request) || GenericUtil.isGenericCall(request)) { - request.setParams(new Object[] {new Wrapper(request.getParams())}); - request.setParamsTypes(new Class[] {Wrapper.class}); - return; - } - - // multi params 兼容2020.0.1版本根据参数个数 > 1 判断是否需要wrap的场景 - if (request.getParamsTypes() != null && request.getParamsTypes().length > 1) { - request.setParams(new Object[] {new Wrapper(request.getParams())}); - request.setParamsTypes(new Class[] {Wrapper.class}); - return; - } - } - - /** - * 兼容Brpc协议在落地时的各种兼容问题 - * - * @param response - */ - public static void wrapRespResult(Response response) { - // serializeMode is pb2-java - String serializeMode = BrpcProtocol.bodySerMode(response.getRequest()); - if (!StringUtils.isEmpty(serializeMode) && serializeMode.equalsIgnoreCase(Constants.PROTO2_JAVA_MODE)) { - response.setResult(new Wrapper(response.getResult())); - response.setReturnType(Wrapper.class); - return; - } - - if (GenericUtil.isGenericMsg(response)) { // generic - response.setResult(new Wrapper(response.getResult())); - response.setReturnType(Wrapper.class); - return; - } - } - - public static boolean checkRequest(Request request) throws StarlightRpcException { - // serializeMode is proto2-java - String serializeMode = BrpcProtocol.bodySerMode(request); - - if (serializeMode == null || // default = pb2-std - serializeMode.equals(Constants.PROTO2_STD_MODE)) { - if (request.getParamsTypes().length > 1 && !GenericUtil.isGenericCall(request)) { - - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Multi-parameter calls are not allowed when use brpc std. " - + "To avoid exception use pb2-java serializeMode or Modify parameter type."); - } - - if (Collection.class.isAssignableFrom(request.getReturnType()) - || Map.class.isAssignableFrom(request.getReturnType())) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Return type is Collection or Map are not allowed when use brpc std. " - + "To avoid exception use pb2-java serializeMode or Modify return type."); - } - } - - // protobuf message not support Multi-parameter - if (request.getParamsTypes() != null && request.getParamsTypes().length > 1 - && MessageLite.class.isAssignableFrom(request.getParamsTypes()[0])) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "Multi-parameter calls are not allowed when use brpc std(protobuf message). " - + "To avoid exception modify method parameter info: only 1 param."); - } - - return true; - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcRequestMeta.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcRequestMeta.java deleted file mode 100644 index 2879ecf0..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcRequestMeta.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.thirdparty.protostuff.Tag; - -import java.util.List; - -/** - * Created by liuruisen on 2020/8/27. - */ -public class BrpcRequestMeta { - /** - * message RpcRequestMeta { required string service_name = 1; required string method_name = 2; optional int64 log_id - * = 3; optional int64 trace_id = 4; optional int64 span_id = 5; optional int64 parent_span_id = 6; repeated - * RpcRequestMetaExtField ext_fields = 7; - * - * optional StarlightRequestMeta starlight_request_meta = 1000; // starlight extension } - */ - @Tag(1) - private String serviceName; - - @Tag(2) - private String methodName; - - @Tag(3) - private Long logId; - - @Tag(4) - private Long traceId; - - @Tag(5) - private Long spanId; - - @Tag(6) - private Long parentSpanId; - - @Tag(7) - private List extFields; - - @Tag(1000) - private StarlightRequestMeta starlightRequestMeta; // 标准brpc的starlight扩展 - - public String getServiceName() { - return serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public String getMethodName() { - return methodName; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - public Long getLogId() { - return logId; - } - - public void setLogId(Long logId) { - this.logId = logId; - } - - public Long getTraceId() { - return traceId; - } - - public void setTraceId(Long traceId) { - this.traceId = traceId; - } - - public Long getSpanId() { - return spanId; - } - - public void setSpanId(Long spanId) { - this.spanId = spanId; - } - - public Long getParentSpanId() { - return parentSpanId; - } - - public void setParentSpanId(Long parentSpanId) { - this.parentSpanId = parentSpanId; - } - - public List getExtFields() { - return extFields; - } - - public void setExtFields(List extFields) { - this.extFields = extFields; - } - - public StarlightRequestMeta getStarlightRequestMeta() { - return starlightRequestMeta; - } - - public void setStarlightRequestMeta(StarlightRequestMeta starlightRequestMeta) { - this.starlightRequestMeta = starlightRequestMeta; - } - - public static final class BrpcRequestMetaExt { - - /** - * message RpcRequestMetaExtField { required string key = 1; required string value = 2; } - */ - - private String key; - - private String value; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcResponseMeta.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcResponseMeta.java deleted file mode 100644 index 864c8845..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcResponseMeta.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.thirdparty.protostuff.Tag; - -/** - * Created by liuruisen on 2020/8/27. - */ -public class BrpcResponseMeta { - - /** - * message RpcResponseMeta { optional Integer32 error_code = 1; optional string error_text = 2; - * - * optional StarlightResponseMeta starlight_response_meta = 1000; // starlight extension } - */ - @Tag(1) - private Integer errorCode; - - @Tag(2) - private String errorText; - - @Tag(1000) - private StarlightResponseMeta starlightResponseMeta; - - public Integer getErrorCode() { - return errorCode; - } - - public void setErrorCode(Integer errorCode) { - this.errorCode = errorCode; - } - - public String getErrorText() { - return errorText; - } - - public void setErrorText(String errorText) { - this.errorText = errorText; - } - - public StarlightResponseMeta getStarlightResponseMeta() { - return starlightResponseMeta; - } - - public void setStarlightResponseMeta(StarlightResponseMeta starlightResponseMeta) { - this.starlightResponseMeta = starlightResponseMeta; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcStreamSettings.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcStreamSettings.java deleted file mode 100644 index 0d5e90ce..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/BrpcStreamSettings.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -/** - * Created by liuruisen on 2020/8/27. - */ -public class BrpcStreamSettings { - - /** - * message StreamSettings { required int64 stream_id = 1; optional bool need_feedback = 2 [default = false]; - * optional bool writable = 3 [default = false]; } - */ - - private Long streamId; - - private boolean needFeedback = false; - - private boolean writable = false; - - public Long getStreamId() { - return streamId; - } - - public void setStreamId(Long streamId) { - this.streamId = streamId; - } - - public boolean isNeedFeedback() { - return needFeedback; - } - - public void setNeedFeedback(boolean needFeedback) { - this.needFeedback = needFeedback; - } - - public boolean isWritable() { - return writable; - } - - public void setWritable(boolean writable) { - this.writable = writable; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/CodeMapping.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/CodeMapping.java deleted file mode 100644 index aedb6318..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/CodeMapping.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.thirdparty.google.common.collect.BiMap; -import com.baidu.cloud.thirdparty.google.common.collect.HashBiMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Status code mapping between Starlight and Brpc Created by liuruisen on 2020/11/9. - */ -public class CodeMapping { - - private static final Logger LOGGER = LoggerFactory.getLogger(CodeMapping.class); - - // Errno caused by client - /* - Service not found - */ - public static final Integer ENOSERVICE = 1001; - /* - Method not found - */ - public static final Integer ENOMETHOD = 1002; - /* - Bad Request - */ - public static final Integer EREQUEST = 1003; - /* - Unauthorized - */ - public static final Integer EAUTH = 1004; - /* - Too many sub calls failed - */ - public static final Integer ETOOMANYFAILS = 1005; - /* - [Internal] ParallelChannel finished - */ - public static final Integer EPCHANFINISH = 1006; - /* - Sending backup request - */ - public static final Integer EBACKUPREQUEST = 1007; - /* - RPC call is timed out - */ - public static final Integer ERPCTIMEDOUT = 1008; - /* - Broken socket - */ - public static final Integer EFAILEDSOCKET = 1009; - /* - Bad http call - */ - public static final Integer EHTTP = 1010; - /* - The server is overcrowded - */ - public static final Integer EOVERCROWDED = 1011; - /* - RtmpRetryingClientStream is publishable - */ - public static final Integer ERTMPPUBLISHABLE = 1012; - /* - createStream was rejected by the RTMP server - */ - public static final Integer ERTMPCREATESTREAM = 1013; - /* - Got EOF - */ - public static final Integer EEOF = 1014; - /* - The socket was not needed - */ - public static final Integer EUNUSED = 1015; - /* - SSL related error - */ - public static final Integer ESSL = 1016; - - // Errno caused by server - /* - Internal Server Error - */ - public static final Integer EINTERNAL = 2001; - /* - Bad Response - */ - public static final Integer ERESPONSE = 2002; - /* - Server is stopping - */ - public static final Integer ELOGOFF = 2003; - /* - Reached server's limit on resources - */ - public static final Integer ELIMIT = 2004; - /* - Close socket initiatively - */ - public static final Integer ECLOSE = 2005; - /* - Failed Itp response - */ - public static final Integer EITP = 2006; - - private static final BiMap starlightToBrpcCodeMap; - - static { - starlightToBrpcCodeMap = HashBiMap.create(); - starlightToBrpcCodeMap.put(StarlightRpcException.BAD_REQUEST, EREQUEST); - starlightToBrpcCodeMap.put(StarlightRpcException.SERVICE_NOT_FOUND_EXCEPTION, ENOSERVICE); - starlightToBrpcCodeMap.put(StarlightRpcException.METHOD_NOT_FOUND_EXCEPTION, ENOMETHOD); - starlightToBrpcCodeMap.put(StarlightRpcException.INTERNAL_SERVER_ERROR, EINTERNAL); - starlightToBrpcCodeMap.put(StarlightRpcException.TIME_OUT_EXCEPTION, ERPCTIMEDOUT); - } - - /** - * Get the mapped value of StarlightNo - * - * @param starlightNo - * @return BrpcNo - */ - public static Integer getBrpcMappingOfStarlightNo(Integer starlightNo) { - - if (starlightNo.equals(Constants.SUCCESS_CODE)) { - return 0; - } - - Integer mappingNo = starlightToBrpcCodeMap.get(starlightNo); - if (mappingNo != null) { - return mappingNo; - } - - if (starlightNo >= TransportException.CONNECT_EXCEPTION) { - return EFAILEDSOCKET; - } - - return EINTERNAL; - } - - /** - * Get the mapped value of BrpcNo - * - * @param brpcNo - * @return StarlightNo - */ - public static Integer getStarlightMappingOfBrpcNo(Integer brpcNo) { - - if (brpcNo.equals(0)) { - return Constants.SUCCESS_CODE; - } - - if (brpcNo.equals(Constants.SUCCESS_CODE)) { - LOGGER.warn("The brpc return code is 200, please make sure this is correct. " - + "Maybe use an old version in sever(less than 2020.0.1-SNAPSHOT)"); - return Constants.SUCCESS_CODE; - } - - Integer mappingNo = starlightToBrpcCodeMap.inverse().get(brpcNo); - if (mappingNo != null) { - return mappingNo; - } - - return StarlightRpcException.INTERNAL_SERVER_ERROR; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightRequestMeta.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightRequestMeta.java deleted file mode 100644 index 538da59e..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightRequestMeta.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import java.util.Map; - -/** - * 适配Java生态,用于传输标准C版Brpc协议不支持,但Java生态里需要存在的meta Created by liuruisen on 2021/3/16. - */ -public class StarlightRequestMeta { - - /** - * 标准Brpc协议仅支持传输 key type String, value type string的attach信息 为兼容从stargate迁移到brpc的已有场景,增加此字段扩展 - */ - private Map starlightExtFields; - - public Map getStarlightExtFields() { - return starlightExtFields; - } - - public void setStarlightExtFields(Map starlightExtFields) { - this.starlightExtFields = starlightExtFields; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightResponseMeta.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightResponseMeta.java deleted file mode 100644 index 0caea169..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/java/com/baidu/cloud/starlight/protocol/brpc/StarlightResponseMeta.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import java.util.Map; - -/** - * 适配Java生态,用于传输标准C版Brpc协议不支持,但Java生态里需要存在的meta Created by liuruisen on 2021/5/12. - */ -public class StarlightResponseMeta { - - /** - * 仅用于传输servRecvReqTime / servCost / servExecMethod / tid 标准Brpc协议response meta中不能传输kv attach信息, - * - */ - private Map starlightExtFields; - - public Map getStarlightExtFields() { - return starlightExtFields; - } - - public void setStarlightExtFields(Map starlightExtFields) { - this.starlightExtFields = starlightExtFields; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol b/starlight/starlight-protocol/starlight-protocol-brpc/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol deleted file mode 100644 index 254fe0f2..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.protocol.brpc.BrpcProtocol \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoderTest.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoderTest.java deleted file mode 100644 index 078783a1..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcDecoderTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class BrpcDecoderTest { - - private BrpcDecoder brpcDecoder = new BrpcDecoder(); - - private BrpcEncoder brpcEncoder = new BrpcEncoder(); - - private ByteBuf requestBuf; - private ByteBuf responseBuf; - - private RpcRequest rpcRequest; - - private RpcResponse rpcResponse; - - @Before - public void init() { - Map kvMap = new HashMap<>(); - kvMap.put(BrpcProtocol.AUTH_KEY, "3456789"); - kvMap.put(Constants.TRACE_ID_KEY, 123l); - kvMap.put(Constants.SPAN_ID_KEY, 2l); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, 1l); - kvMap.put(BrpcProtocol.BINARY_ATTACH_KEY, "hello".getBytes()); - kvMap.put("Key1", "Value1"); - - // starlight request meta test - kvMap.put("Key3", 1L); - kvMap.put("Key4", 123456); - kvMap.put("Key5", 123.123f); - - brpcEncoder = new BrpcEncoder(); - - rpcRequest = new RpcRequest(); - rpcRequest.setMethodName("init"); - rpcRequest.setServiceClass(this.getClass()); - rpcRequest.setServiceConfig(new ServiceConfig()); - rpcRequest.setParams(new Object[] {"Test"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - rpcRequest.setProtocolName("brpc"); - rpcRequest.setAttachmentKv(kvMap); - - brpcEncoder.encodeBody(rpcRequest); - requestBuf = brpcEncoder.encode(rpcRequest); - - rpcResponse = new RpcResponse(); - rpcResponse.setResult("Test"); - rpcResponse.setReturnType(String.class); - rpcResponse.setStatus(Constants.SUCCESS_CODE); - rpcResponse.setErrorMsg(""); - rpcResponse.setProtocolName("brpc"); - rpcResponse.setRequest(rpcRequest); - kvMap.remove(BrpcProtocol.BINARY_ATTACH_KEY); - kvMap.remove(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - rpcResponse.setAttachmentKv(kvMap); - - brpcEncoder.encodeBody(rpcResponse); - responseBuf = brpcEncoder.encode(rpcResponse); - } - - @Test - public void decode() { - DynamicCompositeByteBuf byteBuf = new DynamicCompositeByteBuf(); - byteBuf.addBuffer(requestBuf); - RpcRequest rpcRequest = (RpcRequest) brpcDecoder.decode(byteBuf); - // request rpc meta check - Assert.assertTrue(rpcRequest.getMethodName().equals("init")); - Assert.assertEquals(1L, rpcRequest.getAttachmentKv().get("Key3")); - Assert.assertEquals(123456, rpcRequest.getAttachmentKv().get("Key4")); - Assert.assertEquals(123.123f, rpcRequest.getAttachmentKv().get("Key5")); - Assert.assertEquals("hello".getBytes().length, - rpcRequest.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY)); - - // request rpc body check - rpcRequest.setParamsTypes(new Class[] {String.class}); - brpcDecoder.decodeBody(rpcRequest); - Assert.assertTrue(rpcRequest.getParams()[0].equals("Test")); - - byteBuf.addBuffer(responseBuf); - RpcResponse rpcResponse = (RpcResponse) brpcDecoder.decode(byteBuf); - rpcResponse.setRequest(rpcRequest); - Assert.assertTrue(rpcResponse.getStatus() == Constants.SUCCESS_CODE); - rpcResponse.setReturnType(String.class); - brpcDecoder.decodeBody(rpcResponse); - Assert.assertTrue(rpcResponse.getResult().equals("Test")); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoderTest.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoderTest.java deleted file mode 100644 index bf618fb2..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcEncoderTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.AbstractMsgBase; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static com.baidu.cloud.starlight.api.exception.CodecException.BODY_ENCODE_EXCEPTION; -import static com.baidu.cloud.starlight.api.exception.CodecException.PROTOCOL_ENCODE_EXCEPTION; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class BrpcEncoderTest { - - private RpcRequest rpcRequest; - - private RpcResponse rpcResponse; - - private BrpcEncoder brpcEncoder; - - @Before - public void init() { - Map kvMap = new HashMap<>(); - kvMap.put(BrpcProtocol.AUTH_KEY, "3456789"); - kvMap.put(Constants.TRACE_ID_KEY, 123l); - kvMap.put(Constants.SPAN_ID_KEY, 2l); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, 1l); - kvMap.put(BrpcProtocol.BINARY_ATTACH_KEY, "hello".getBytes()); - kvMap.put("Key1", "Value1"); - - rpcRequest = new RpcRequest(); - rpcRequest.setMethodName("init"); - rpcRequest.setServiceClass(this.getClass()); - rpcRequest.setServiceConfig(new ServiceConfig()); - rpcRequest.setParams(new Object[] {"Test"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - rpcRequest.setProtocolName("brpc"); - rpcRequest.setAttachmentKv(kvMap); - - rpcResponse = new RpcResponse(); - rpcResponse.setRequest(rpcRequest); - rpcResponse.setResult("Test"); - rpcResponse.setReturnType(String.class); - rpcResponse.setStatus(Constants.SUCCESS_CODE); - rpcResponse.setErrorMsg(""); - rpcResponse.setProtocolName("brpc"); - rpcResponse.setAttachmentKv(kvMap); - - brpcEncoder = new BrpcEncoder(); - } - - @Test - public void encode() { - // encode request - ByteBuf requestByte = brpcEncoder.encode(rpcRequest); - Assert.assertTrue(requestByte.readableBytes() > 0); - System.out.println(requestByte.readInt()); - System.out.println(requestByte.readByte()); - - // encode response - ByteBuf responseByte = brpcEncoder.encode(rpcResponse); - Assert.assertTrue(responseByte.readableBytes() > 0); - System.out.println(responseByte.readInt()); - System.out.println(responseByte.readByte()); - - // encode null - try { - brpcEncoder.encode(null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == PROTOCOL_ENCODE_EXCEPTION); - } - - // encode error type message - try { - brpcEncoder.encode(new AbstractMsgBase() {}); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == PROTOCOL_ENCODE_EXCEPTION); - } - } - - @Test - public void encodeBody() { - // encode request body - brpcEncoder.encodeBody(rpcRequest); - Assert.assertTrue(rpcRequest.getBodyBytes().length > 0); - Integer attachBinartSize = (Integer) rpcRequest.getAttachmentKv().get(BrpcProtocol.BINARY_ATTACH_SIZE_KEY); - Assert.assertEquals("hello".getBytes().length, (int) attachBinartSize); - - // encode response body - brpcEncoder.encodeBody(rpcResponse); - Assert.assertTrue(rpcResponse.getBodyBytes().length > 0); - - // encode null - try { - brpcEncoder.encodeBody(null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == BODY_ENCODE_EXCEPTION); - } - - // encode error type message - MsgBase msgBase = new AbstractMsgBase() {}; - msgBase.setBodyBytes(new byte[0]); - brpcEncoder.encodeBody(msgBase); - Assert.assertTrue(msgBase.getBodyBytes().length == 0); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocolTest.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocolTest.java deleted file mode 100644 index 5aeb305f..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/BrpcProtocolTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.model.Wrapper; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.serialization.serializer.ProtoStuffSerializer; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class BrpcProtocolTest { - - private BrpcProtocol brpcProtocol = new BrpcProtocol(); - - @Test - public void getEncoder() { - assertTrue(brpcProtocol.getEncoder() instanceof BrpcEncoder); - } - - @Test - public void getDecoder() { - assertTrue(brpcProtocol.getDecoder() instanceof BrpcDecoder); - } - - @Test - public void getHeartbeatTrigger() { - assertTrue(brpcProtocol.getHeartbeatTrigger() == null); - } - - @Test - public void getSerialize() { - assertTrue(brpcProtocol.getSerialize(BrpcProtocol.SERIALIZER_TYPE_PROTOSTUFF) instanceof ProtoStuffSerializer); - } - - @Test - public void wrapRequest() { - Request request = new RpcRequest(); - request.setAttachmentKv(new HashMap<>()); - request.setParamsTypes(new Class[] {TestModel.class}); - request.setParams(new Object[] {new TestModel()}); - - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof TestModel); - assertTrue(TestModel.class.isAssignableFrom(request.getParamsTypes()[0])); - - // multi params - request.setParamsTypes(new Class[] {TestModel.class, String.class}); - request.setParams(new Object[] {new TestModel(), "test"}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - // Map - request.setParamsTypes(new Class[] {Map.class}); - request.setParams(new Object[] {new HashMap<>()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Map); - assertTrue(Map.class.isAssignableFrom(request.getParamsTypes()[0])); - - // Collection - request.setParamsTypes(new Class[] {ArrayList.class}); - request.setParams(new Object[] {new ArrayList<>()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof List); - assertTrue(List.class.isAssignableFrom(request.getParamsTypes()[0])); - - // Generic - GenericUtil.markGeneric(request); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - // serialize mode proto2-java - request.getAttachmentKv().put(Constants.SERIALIZER_MODE_KEY, Constants.PROTO2_JAVA_MODE); - - request.setParamsTypes(new Class[] {TestModel.class}); - request.setParams(new Object[] {new TestModel()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - // Map - request.setParamsTypes(new Class[] {Map.class}); - request.setParams(new Object[] {new HashMap<>()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - // Collection - request.setParamsTypes(new Class[] {ArrayList.class}); - request.setParams(new Object[] {new ArrayList<>()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - // 2020.0.1-SNAPSHOT场景,serializeMode为null,参数为单个或者多个 - request.getAttachmentKv().remove(Constants.SERIALIZER_MODE_KEY); - request.getAttachmentKv().remove(Constants.IS_GENERIC_KEY); - - request.setParamsTypes(new Class[] {TestModel.class}); // 模拟2020.0.1的客户端请求参数 - request.setParams(new Object[] {new TestModel()}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof TestModel); - assertTrue(TestModel.class.isAssignableFrom(request.getParamsTypes()[0])); - - request.setParamsTypes(new Class[] {String.class, Long.class, TestModel.class}); - request.setParams(new Object[] {"123", 123L, new TestModel()}); // 多参数 - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(request.getParamsTypes()[0])); - - request.setParamsTypes(new Class[] {Long.class}); - request.setParams(new Object[] {123L}); - BrpcProtocol.wrapReqParams(request); - assertTrue(request.getParams()[0] instanceof Long); - assertTrue(Long.class.isAssignableFrom(request.getParamsTypes()[0])); - } - - @Test - public void wrapResponse() { - Response response = new RpcResponse(); - response.setRequest(new RpcRequest()); - - response.setStatus(Constants.SUCCESS_CODE); - response.setReturnType(TestModel.class); - response.setResult(new TestModel()); - - // normal - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof TestModel); - assertTrue(TestModel.class.isAssignableFrom(response.getReturnType())); - - // Collection - response.setReturnType(ArrayList.class); - response.setResult(new ArrayList<>()); - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof List); - assertTrue(List.class.isAssignableFrom(response.getReturnType())); - - // Map - response.setReturnType(Map.class); - response.setResult(new HashMap<>()); - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof Map); - assertTrue(Map.class.isAssignableFrom(response.getReturnType())); - - // Generic - GenericUtil.markGeneric(response); - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(response.getReturnType())); - - // proto2-java - response.getAttachmentKv().remove(Constants.IS_GENERIC_KEY); - - Request request = new RpcRequest(); - request.getAttachmentKv().put(Constants.SERIALIZER_MODE_KEY, Constants.PROTO2_JAVA_MODE); - response.setRequest(request); - - response.setReturnType(Map.class); - response.setResult(new HashMap<>()); - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(response.getReturnType())); - - response.setReturnType(ArrayList.class); - response.setResult(new ArrayList<>()); - BrpcProtocol.wrapRespResult(response); - assertTrue(response.getResult() instanceof Wrapper); - assertTrue(Wrapper.class.isAssignableFrom(response.getReturnType())); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/TestModel.java b/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/TestModel.java deleted file mode 100644 index d35884ff..00000000 --- a/starlight/starlight-protocol/starlight-protocol-brpc/src/test/java/com/baidu/cloud/starlight/protocol/brpc/TestModel.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.brpc; - -/** - * Created by liuruisen on 2021/2/7. - */ -public class TestModel { - - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/pom.xml b/starlight/starlight-protocol/starlight-protocol-http/pom.xml deleted file mode 100644 index 64b123c1..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/pom.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight-protocol - 2025.0.1-SNAPSHOT - - - starlight-protocol-http - - diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocol.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocol.java deleted file mode 100644 index bca0bf6a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocol.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletRequest; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; - -/** - * HttpProtocol Created by liuruisen on 2020/5/27. - */ -public abstract class AbstractHttpProtocol implements Protocol { - - private final static Serializer serializer = new JsonSerializer(); - - public final static String X_STARLIGHT_ID = "x-starlight-id"; - - public static final String CONTENT_TYPE_JSON = "application/json"; - - public static final String ENCODING = "UTF-8"; - - public static final Integer UNKNOW_STATUS = 99999; - - @Override - public HeartbeatTrigger getHeartbeatTrigger() { - return null; - } - - @Override - public Serializer getSerialize() { - return serializer; - } - - /** - * If the request is servletRequest, such as # methodName(HttpServletRequest, HttpServletResponse) # - * - * @param request - * @return - */ - public static boolean isServletRequest(Request request) { - Class[] paramTypes = request.getParamsTypes(); - if (paramTypes != null) { - for (Class paramClass : paramTypes) { - if (HttpServletResponse.class.isAssignableFrom(paramClass)) { - return true; - } - - if (HttpServletRequest.class.isAssignableFrom(paramClass)) { - return true; - } - } - } - return false; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpDecoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpDecoder.java deleted file mode 100644 index 17c02773..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpDecoder.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpMessage; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; - -/** - * Decode ByteBuf to MsgBase, use {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObjectDecoder} Decode - * msg body: from bytes to pojo. Created by liuruisen on 2020/5/27. - */ -public abstract class HttpDecoder implements ProtocolDecoder { - - protected static final Logger LOGGER = LoggerFactory.getLogger(HttpDecoder.class); - - @Override - public MsgBase decode(DynamicCompositeByteBuf input) throws CodecException { - - if (input.readableBytes() <= 0) { - throw new CodecException(CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION, - "Too little data to parse using Http"); // wait and retry - } - // 解析请求或者响应行,能解出来证明是Http协议的数据,不能解出来证明不是 - - // NOTICE 暂无办法复现、构造如下异常: - // NOTICE PROTOCOL_INSUFFICIENT_DATA_EXCEPTION PROTOCOL_DECODE_NOTMATCH_EXCEPTION PROTOCOL_DECODE_EXCEPTION - MsgBase msgBase = null; - ByteBuf byteBuf = input.retainedSlice(input.readableBytes()); - FullHttpMessage httpMessage = null; - EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpRequestResponseDecoder()); - try { - embeddedChannel.writeInbound(byteBuf); - httpMessage = embeddedChannel.readInbound(); - if (httpMessage == null || !httpMessage.decoderResult().isSuccess()) { - LOGGER.debug("Cannot use Http protocol to decode: ", - httpMessage == null ? "result is null" : "result failed " + httpMessage.decoderResult()); - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Cannot use Http protocol to decode: decoded result is null"); - } - - if (httpMessage.headers() != null) { - // request id check, discard - if (httpMessage.headers().get(AbstractHttpProtocol.X_STARLIGHT_ID) == null) { - // support null id for url request (2020.10.16 for ironman) - httpMessage.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, "-1"); // -1 represent none - LOGGER.debug("Starlight id is null, make sure it is correct"); - } - - // content type check - String contentTypeAndEncoding = httpMessage.headers().get(HttpHeaderNames.CONTENT_TYPE); - if (!StringUtils.isBlank(contentTypeAndEncoding)) { - String[] splits = contentTypeAndEncoding.split(";"); - String contentType = splits[0]; - // not support content_type, discard - if (!contentType.equals(AbstractHttpProtocol.CONTENT_TYPE_JSON)) { - - /* - * httpMessage = null; input.skipBytes(byteBuf.readerIndex()); throw new - * CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - * "Cannot use httpDecoder to decode bytes"); - */ - // this protocol can only deal with http protobuf and http json request. - // record - LOGGER.warn("ContentType id is not application/json, make sure it is a browser request"); - } - } - } else { - LOGGER.error("The http request not have headers, this is unlikely to happen"); - } - - if (httpMessage instanceof FullHttpRequest) { - msgBase = reverseConvertRequest((FullHttpRequest) httpMessage); - } - - if (httpMessage instanceof FullHttpResponse) { - msgBase = reverseConvertResponse((FullHttpResponse) httpMessage); - } - } finally { - // When there is only one http protocol, and httpMessage is not null, we think decode success and skip bytes - // FIXME When multiple http protocols are implemented, please check if the logic here is as expected - if (httpMessage != null && httpMessage.decoderResult().isSuccess() /* && msgBase != null */) { - input.skipBytes(byteBuf.readerIndex()); - } - LOGGER.debug("input.retainedSlice bytebuf refCnt {}", byteBuf.refCnt()); - byteBuf.release(); - embeddedChannel.close(); - } - - return msgBase; - } - - @Override - public void decodeBody(MsgBase msgBase) throws CodecException { - if (msgBase == null) { - throw new CodecException(CodecException.BODY_DECODE_EXCEPTION, "Message is null to decode"); - } - - if (msgBase instanceof Request) { - decodeRequestBody((Request) msgBase); - } - - if (msgBase instanceof Response) { - decodeResponseBody((Response) msgBase); - } - } - - private void decodeRequestBody(Request request) { - if (request.getParams() == null || request.getParams().length == 0) { - return; - } - - // FIXME generic调用 - if (request.getParamsTypes() == null) { // paramTypes is get from target Method when Processor#process - throw new CodecException(CodecException.BODY_DECODE_EXCEPTION, "Body data type is null"); - } - - for (int i = 0; i < request.getParams().length; i++) { // find byte[] params and de serialize - if (request.getParams()[i] instanceof byte[]) { // TODO check and vertify - byte[] bodyBytes = (byte[]) request.getParams()[i]; - if (bodyBytes != null && bodyBytes.length > 0) { - Type bodyType = request.getGenericParamsTypes()[i]; - Serializer serializer = serializer(request.getProtocolName()); - Object bodyObj = serializer.deserialize(bodyBytes, bodyType); - request.getParams()[i] = bodyObj; - break; // only one requestBody - } - } - } - } - - protected void decodeResponseBody(Response response) { - // TODO generic call - if (response.getBodyBytes() == null) { - return; - } - Serializer serializer = serializer(response.getProtocolName()); - if (response.getStatus() != Constants.SUCCESS_CODE) { // error: response content is error message - response.setErrorMsg((String) serializer.deserialize(response.getBodyBytes(), String.class)); - } else { // success: response content is response message - if (response.getReturnType() == null) { // body type is get from target Method in ClientProcessor - throw new CodecException(CodecException.BODY_DECODE_EXCEPTION, "Body data type is null"); - } - response.setResult(serializer.deserialize(response.getBodyBytes(), response.getGenericReturnType())); - } - } - - /** - * TODO 结合逻辑看下此部分是否可以抽象出公共逻辑,release的逻辑想办法移动到这里 Reverse convert {@link FullHttpRequest} to {@link RpcRequest} in - * accordance with protocol and programming contract. - * - * @param httpRequest - * @return - */ - protected abstract Request reverseConvertRequest(FullHttpRequest httpRequest); - - /** - * Reverse convert {@link FullHttpResponse} to {@link RpcResponse} in accordance with protocol and programming - * contract. - *

- * Convert HttpResponse to Response - *

    - *
  • Step1: convert headers to kvMap, requestId
  • - *
  • Step2: convert content to bodyBytes
  • - *
- * - * @param httpResponse - * @return - */ - protected Response reverseConvertResponse(FullHttpResponse httpResponse) { - try { - long corelationId = Long.parseLong(httpResponse.headers().get(AbstractHttpProtocol.X_STARLIGHT_ID)); - Response response = new RpcResponse(corelationId); - // FIXME CompressType - - // set attachmentKv - response.setAttachmentKv(new HashMap<>()); - for (Map.Entry entry : httpResponse.headers().entries()) { - response.getAttachmentKv().put(entry.getKey(), entry.getValue()); - } - // set status - response.setStatus(httpResponse.status().code()); - if (!httpResponse.status().equals(HttpResponseStatus.OK)) { - LOGGER.warn("Id:{}, response status is {}", response.getId(), response.getStatus()); - response.setErrorMsg( - "Response is error, Id:" + response.getId() + ", response status is " + response.getStatus()); - } - // set bodyBytes - ByteBuf content = httpResponse.content(); - if (content != null && content.readableBytes() > 0) { - byte[] contentBytes = new byte[content.readableBytes()]; - content.readBytes(contentBytes); - response.setBodyBytes(contentBytes); - } - return response; - } finally { - httpResponse.release(); - } - } - - protected Serializer serializer(String protocolName) { - Protocol brpcProtocol = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName); - return brpcProtocol.getSerialize(); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpEncoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpEncoder.java deleted file mode 100644 index 15f9559f..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpEncoder.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.starlight.protocol.http.springrest.NettyServletResponseAdaptor; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpRequestEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; - -import java.util.Map; - -/** - * Encode {@link MsgBase} to {@link ByteBuf}, use - * {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObjectEncoder}. Encode msgBase body: from Pojo to - * bytes. Created by liuruisen on 2020/5/27. - */ -public abstract class HttpEncoder implements ProtocolEncoder { - - private static final Integer EMPTY_BODY_LENGTH = 0; - - @Override - public ByteBuf encode(MsgBase input) throws CodecException { - if (input == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, "MsgBase is null, cannot encode"); - } - - if (input instanceof Request) { - return encodeRequest((Request) input); - } - - if (input instanceof Response) { - return encodeResponse((Response) input); - } - - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "MsgBase type is illegal {" + input.getClass().getName() + "}, cannot encode"); - - } - - /** - * Encode Request to ByteBuf - * - * @param request - * @return - */ - private ByteBuf encodeRequest(Request request) { - - if (request.getParams() == null || !(request.getParams()[0] instanceof FullHttpRequest)) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "RpcRequest have not been converted to HttpRequest, please check"); - } - - /** - * {@link #encodeRequestBody(Request)} will convert RpcRequest to FullHttpRequest - */ - FullHttpRequest httpRequest = (FullHttpRequest) request.getParams()[0]; - - /** - * Use EmbeddedChannel and HttpRequestEncoder to encode FullHttpRequest NOTICE: - * HttpResponseEncoder的结果是直接分配在DirectBuf中的,使用完毕记得release - */ - EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpRequestEncoder()); - try { - // FIXME 可根据实际情况调整channel的配置,主要是关于alloc().buffer()的配置 - embeddedChannel.writeOutbound(httpRequest); - if (embeddedChannel.outboundMessages() != null && embeddedChannel.outboundMessages().size() > 1) { - ByteBuf[] outputBufs = new ByteBuf[embeddedChannel.outboundMessages().size()]; - embeddedChannel.outboundMessages().toArray(outputBufs); - return Unpooled.wrappedBuffer(outputBufs); - } - return embeddedChannel.readOutbound(); - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode Request to ByteBuf failed: " + e.getMessage()); - } finally { - embeddedChannel.close(); - } - } - - /** - * Encode Response to ByteBuf - * - * @param response - * @return - */ - protected ByteBuf encodeResponse(Response response) { - if (response.getResult() == null || !(response.getResult() instanceof FullHttpResponse)) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "RpcResponse have not been converted to HttpResponse, please check"); - } - - FullHttpResponse httpResponse = (FullHttpResponse) response.getResult(); - - // NOTICE: HttpResponseEncoder的结果是直接分配在DirectBuf中的,使用完毕记得release - EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpResponseEncoder()); - try { - embeddedChannel.writeOutbound(httpResponse); - if (embeddedChannel.outboundMessages() != null && embeddedChannel.outboundMessages().size() > 1) { - ByteBuf[] outputBufs = new ByteBuf[embeddedChannel.outboundMessages().size()]; - embeddedChannel.outboundMessages().toArray(outputBufs); - return Unpooled.wrappedBuffer(outputBufs); - } - return embeddedChannel.readOutbound(); - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode Response to ByteBuf failed: " + e.getMessage()); - } finally { - embeddedChannel.close(); - } - } - - /** - * Convert MsgBase to {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpMessage} - * - * @param msgBase - * @throws CodecException - */ - @Override - public void encodeBody(MsgBase msgBase) throws CodecException { - if (msgBase == null) { - throw new CodecException(CodecException.BODY_ENCODE_EXCEPTION, "MsgBase is null, cannot encode"); - } - - if (msgBase instanceof Request) { - encodeRequestBody((Request) msgBase); - } - - if (msgBase instanceof Response) { - encodeResponseBody((Response) msgBase); - } - } - - private void encodeRequestBody(Request request) { - FullHttpRequest httpRequest = convertRequest(request); - /** - * EncodeRequestBody only serialize body an encode Response to FullHttpResponse. So we change params to - * FullHttpRequest. {@link #encode(MsgBase)} method will get params from Request.params and convert to Request - * byteBuf. - */ - request.setParams(new Object[] {httpRequest}); - } - - protected void encodeResponseBody(Response response) { - FullHttpResponse httpResponse = convertResponse(response); - /** - * EncodeResponseBody only serialize body an encode Response to FullHttpResponse. So we fill response result - * with FullHttpResponse. {@link #encode(MsgBase)} method will get body from reponse.result and convert to - * Response byteBuf. - */ - response.setResult(httpResponse); - } - - /** - * Convert {@link RpcRequest} to {@link FullHttpRequest} in accordance with protocol and programming contract. - * - * @param rpcRequest - * @return - */ - protected abstract FullHttpRequest convertRequest(Request rpcRequest); - - /** - * Convert {@link RpcResponse} to {@link FullHttpResponse} in accordance with protocol and programming contract. - * - * @param response - * @return - */ - protected FullHttpResponse convertResponse(Response response) { - - // <1> convert Response to FullHttpResponse - FullHttpResponse httpResponse = null; - - if (hasHttpServletResponse(response)) { // 支持servlet请求的场景 - NettyServletResponseAdaptor servletResponseAdaptor = servletResponseAdaptor(response); - httpResponse = servletResponseAdaptor.getNettyHttpResponse(); - } else { - httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.valueOf(AbstractHttpProtocol.UNKNOW_STATUS)); - } - - fulfillRpcResponse(httpResponse, response); - // necessary headers - httpResponse.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, response.getId()); // id - if (response.getAttachmentKv() != null && response.getAttachmentKv().size() > 0) { - for (Map.Entry kv : response.getAttachmentKv().entrySet()) { - httpResponse.headers().add(kv.getKey(), kv.getValue()); - } - } - - return httpResponse; - } - - private boolean hasHttpServletResponse(Response response) { - if (response.getRequest() == null) { - return false; - } - - // 兼容 servlet请求,即方法参数中的有HttpServletRequest HttpServletResponse - Class[] paramTypes = response.getRequest().getParamsTypes(); - if (paramTypes != null) { - for (Class paramClass : paramTypes) { - if (HttpServletResponse.class.isAssignableFrom(paramClass)) { - return true; - } - } - } - - Map requestAttachKv = response.getRequest().getAttachmentKv(); - if (requestAttachKv != null && requestAttachKv.get(Constants.SERVLET_RESPONSE_KEY) != null) { - return true; - } - - return false; - } - - private NettyServletResponseAdaptor servletResponseAdaptor(Response response) { - - Object[] params = response.getRequest().getParams(); - if (params != null && params.length > 0) { - for (Object param : params) { - if (param instanceof NettyServletResponseAdaptor) { - return (NettyServletResponseAdaptor) param; - } - } - } - - Map requestAttachKv = response.getRequest().getAttachmentKv(); - if (requestAttachKv != null && requestAttachKv.get(Constants.SERVLET_RESPONSE_KEY) != null) { - return (NettyServletResponseAdaptor) requestAttachKv.remove(Constants.SERVLET_RESPONSE_KEY); - } - - return null; - } - - private Serializer serializer(String protocolName) { - Protocol httpProtocol = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName); - Serializer serializer = httpProtocol.getSerialize(); - return serializer; - } - - protected void fulfillRpcResponse(FullHttpResponse httpResponse, Response response) { - Serializer serializer = serializer(response.getProtocolName()); - - // set response status - if (httpResponse.status() == null || httpResponse.status().code() == AbstractHttpProtocol.UNKNOW_STATUS) { - if (response.getStatus() != Constants.SUCCESS_CODE) { - httpResponse.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); - } else { - httpResponse.setStatus(HttpResponseStatus.OK); - } - } - - // set content - if (!httpResponse.status().equals(HttpResponseStatus.OK) && StringUtils.hasText(response.getErrorMsg())) { - response.setBodyBytes(serializer.serialize(response.getErrorMsg(), String.class)); - } - - if (httpResponse.status().equals(HttpResponseStatus.OK) && response.getResult() != null) { - if (AbstractHttpProtocol.isServletRequest(response.getRequest())) { // servlet request - if (response.getResult().getClass() == byte[].class) { // 返回byte[]的类型 - response.setBodyBytes((byte[]) response.getResult()); - } else if (response.getResult() instanceof String) { // 返回 string 类型 - response.setBodyBytes(((String) response.getResult()).getBytes()); - } else { // 其他类型 - response.setBodyBytes(serializer.serialize(response.getResult(), response.getGenericReturnType())); - } - } else { - response.setBodyBytes(serializer.serialize(response.getResult(), response.getGenericReturnType())); - } - } - // httpResponse.content().clear(); - if (response.getBodyBytes() != null && response.getBodyBytes().length > 0) { - httpResponse.content().writeBytes(response.getBodyBytes()); - } - int contentLength = httpResponse.content().readableBytes(); - httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, contentLength); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseAggregator.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseAggregator.java deleted file mode 100644 index 95db44cb..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseAggregator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObject; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObjectAggregator; -import com.baidu.cloud.thirdparty.netty.util.ReferenceCountUtil; - -import java.util.List; - -/** - * Created by liuruisen on 2020/9/16. - */ -public class HttpRequestResponseAggregator extends HttpObjectAggregator { - - public HttpRequestResponseAggregator(int maxContentLength) { - super(maxContentLength); - } - - /** - * Aggregate http message into full http message by calling - * {@link HttpObjectAggregator#decode(ChannelHandlerContext, Object, List)} - * - * @param ctx - * @param msg - * @param out - * @throws Exception - */ - public void aggregate(final ChannelHandlerContext ctx, Object msg, List out) throws Exception { - - if (acceptInboundMessage(msg)) { - try { - decode(ctx, (HttpObject) msg, out); // aggregate http message - } finally { - ReferenceCountUtil.release(msg); - } - } else { - out.add(msg); - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoder.java deleted file mode 100644 index ce9f71d6..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoder.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMessage; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObjectDecoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; - -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.netty.util.ReferenceCounted; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; - -/** - * Combine {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpRequestDecoder} and - * {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseDecoder} to HttpRequestResponseDecoder. - *

- * Un Thread Safe. Created by liuruisen on 2020/6/1. - */ -public class HttpRequestResponseDecoder extends HttpObjectDecoder { - - private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequestResponseDecoder.class); - - private static final String HTTP = "HTTP"; - - private static final HttpResponseStatus UNKNOWN_STATUS = new HttpResponseStatus(999, "Unknown"); - - private Boolean isRequest = false; - - /** - * 512m - */ - private static final Integer MAX_CONTENT_LENGTH = 512 * 1024 * 1024; - - private static final Integer MAX_HEADER_SIZE = 8192; - - private static final Integer MAX_INIT_LINE_LENGTH = 4096; - - public HttpRequestResponseDecoder() { - super(MAX_INIT_LINE_LENGTH, MAX_HEADER_SIZE, MAX_CONTENT_LENGTH, true); - } - - @Override - protected boolean isDecodingRequest() { - return isRequest; - } - - @Override - protected HttpMessage createMessage(String[] initialLine) throws Exception { - if (initialLine[0].contains(HTTP)) { // response - isRequest = false; - return new DefaultHttpResponse(HttpVersion.valueOf(initialLine[0]), - HttpResponseStatus.valueOf(Integer.parseInt(initialLine[1]), initialLine[2]), validateHeaders); - } else { // request - isRequest = true; - return new DefaultHttpRequest(HttpVersion.valueOf(initialLine[2]), HttpMethod.valueOf(initialLine[0]), - initialLine[1], validateHeaders); - } - } - - @Override - protected HttpMessage createInvalidMessage() { - if (isRequest) { - return new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/bad-request", validateHeaders); - } else { - return new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, UNKNOWN_STATUS, validateHeaders); - } - } - - /** - * 包含针对粘包拆包的处理 - * - * @param ctx - * @param buffer - * @param out - * @throws Exception - */ - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { - - // Store http message part for aggregation in HttpObjectAggregator - List httpMessageParts = new LinkedList<>(); - - // 记录运行过程中所有的parts - List allHttpMessageParts = new LinkedList<>(); - - // Store full http message to return - List fullHttpMessages = new LinkedList<>(); - - HttpRequestResponseAggregator aggregator = new HttpRequestResponseAggregator(MAX_CONTENT_LENGTH); - - try { - while (buffer.isReadable()) { - // <1> decode byteBuf to httpMessage - int oldPartSize = httpMessageParts.size(); - int oldBufferLength = buffer.readableBytes(); - - super.decode(ctx, buffer, httpMessageParts); // produce one more http message part - - // decode one time without producing output, such as READ_CHUNK_DELIMITER BAD_MESSAGE UPGRADED - if (oldPartSize == httpMessageParts.size() && oldBufferLength == buffer.readableBytes()) { - // 有可能是协议不匹配 - LOGGER.warn("Decode one time without reading any bytes, this is unlikely to happen"); - break; - } - - // 第一次decode出请求头,等待后续decode出body - if (httpMessageParts.size() == 1 && httpMessageParts.get(0) instanceof HttpMessage - && buffer.isReadable()) { - HttpMessage requestHeader = (HttpMessage) httpMessageParts.get(0); - String contentLengthStr = requestHeader.headers().get("Content-Length"); - if (StringUtils.isNumeric(contentLengthStr)) { - int length = Integer.parseInt(contentLengthStr); - if (length > MAX_CONTENT_LENGTH) { - LOGGER - .error("Content-Length of request {} is {}, bigger than the max {}", - requestHeader instanceof DefaultHttpRequest - ? ((DefaultHttpRequest) requestHeader).uri() : requestHeader, - length, MAX_CONTENT_LENGTH); - } - LOGGER.debug("Content-Length of request {} is {}, readable bytebuf is {}", - requestHeader instanceof DefaultHttpRequest ? ((DefaultHttpRequest) requestHeader).uri() - : requestHeader, - length, buffer.readableBytes()); - buffer = buffer.readSlice(length); - } - } - allHttpMessageParts.addAll(httpMessageParts); - - // <2> try to aggregate http message into full http message - for (Object httpMessagePart : httpMessageParts) { - aggregator.aggregate(ctx, httpMessagePart, fullHttpMessages); - if (fullHttpMessages.size() > 0) { - out.add(fullHttpMessages.get(0)); - return; - } - } - // clear parts list, because we had aggregated parts before - httpMessageParts.clear(); - } - } finally { - LOGGER.debug("allHttpMessageParts size {}", allHttpMessageParts.size()); - LOGGER.debug("fullHttpMessages size {}", fullHttpMessages.size()); - // httpMessageParts不为空,但fullHttpMessage为空,证明本次解析失败了 - // 释放httpMessageParts防止内存泄露 - if (allHttpMessageParts.size() > 0 && fullHttpMessages.isEmpty()) { - // release拆包时解析了一半的body content - LOGGER.info("allHttpMessageParts size {}, fullHttpMessage size {}, will release", - allHttpMessageParts.size(), fullHttpMessages.size()); - allHttpMessageParts.forEach(part -> { - if (part instanceof ReferenceCounted) { - ReferenceCounted refer = (ReferenceCounted) part; - int refCnt = refer.refCnt(); - if (refCnt > 0) { - refer.release(refCnt); - } - } - }); - } - - if (fullHttpMessages.isEmpty()) { - // release aggregator's currentMessage(directByteBuf) - LOGGER.debug("release aggregator's currentMessage(directByteBuf)"); - aggregator.handlerRemoved(ctx); - } - } - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof ByteBuf) { - List out = new LinkedList<>(); - try { - decode(ctx, (ByteBuf) msg, out); - } catch (Exception e) { - LOGGER.debug( - "Bytebuf cannot be decoded by http protocol, will retry another protocol. " + "the reason is : {}", - e.getMessage()); - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Bytebuf cannot be decoded by http protocol, will retry another protocol. " + "The reason is " - + e.getMessage()); - } finally { - for (Object result : out) { - ctx.fireChannelRead(result); - } - } - } else { - ctx.fireChannelRead(msg); - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStream.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStream.java deleted file mode 100644 index 38633959..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStream.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufInputStream; - -import com.baidu.cloud.thirdparty.servlet.ReadListener; -import com.baidu.cloud.thirdparty.servlet.ServletInputStream; -import java.io.IOException; - -/** - * Wrapper {@link ByteBufInputStream} as ServletInputStream. Used when converting - * {@link com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest} to - * {@link com.baidu.cloud.thirdparty.servlet.ServletRequest}. - * - * @see NettyServletRequestAdaptor#getInputStream() Created by liuruisen on 2020/6/8. - */ -public class ByteBufServletInputStream extends ServletInputStream { - - private final ByteBufInputStream byteBufInputStream; - - public ByteBufServletInputStream(ByteBufInputStream byteBufInputStream) { - this.byteBufInputStream = byteBufInputStream; - } - - @Override - public boolean isFinished() { - try { - return byteBufInputStream.available() == 0; - } catch (IOException e) { - return true; - } - } - - @Override - public boolean isReady() { - try { - return available() > 0; - } catch (IOException e) { - return false; - } - } - - @Override - public void setReadListener(ReadListener readListener) { - throw new UnsupportedOperationException("ByteBufServletInputStream not support setListener"); - } - - @Override - public int read() throws IOException { - return byteBufInputStream.read(); - } - - @Override - public int read(byte[] b) throws IOException { - return byteBufInputStream.read(b); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - return byteBufInputStream.read(b, off, len); - } - - @Override - public long skip(long n) throws IOException { - return byteBufInputStream.skip(n); - } - - @Override - public int available() throws IOException { - return byteBufInputStream.available(); - } - - @Override - public void close() throws IOException { - byteBufInputStream.close(); - } - - @Override - public synchronized void mark(int readlimit) { - byteBufInputStream.mark(readlimit); - } - - @Override - public synchronized void reset() throws IOException { - byteBufInputStream.reset(); - } - - @Override - public boolean markSupported() { - return byteBufInputStream.markSupported(); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStream.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStream.java deleted file mode 100644 index 870f26f3..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStream.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufOutputStream; -import com.baidu.cloud.thirdparty.servlet.ServletOutputStream; -import com.baidu.cloud.thirdparty.servlet.WriteListener; - -import java.io.IOException; - -/** - * Netty implement of ServletOutputStream Created by liuruisen on 2020/10/16. - */ -public class ByteBufServletOutputStream extends ServletOutputStream { - - private ByteBufOutputStream byteBufOutputStream; - - public ByteBufServletOutputStream(ByteBufOutputStream byteBufOutputStream) { - this.byteBufOutputStream = byteBufOutputStream; - } - - @Override - public boolean isReady() { - return byteBufOutputStream.writtenBytes() > 0; - } - - @Override - public void setWriteListener(WriteListener writeListener) { - // FIXME 寻找更优的解法 - throw new UnsupportedOperationException("ByteBufServletOutputStream not support setListener"); - } - - @Override - public void write(int b) throws IOException { - // FIXME 实现过于简单,寻找最优解,最好能结合WriteListener - byteBufOutputStream.write(b); - } - - public void resetBuffer() { - this.byteBufOutputStream.buffer().clear(); - } - - public int getBufferSize() { - return this.byteBufOutputStream.buffer().readableBytes(); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverter.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverter.java deleted file mode 100644 index cc898ed7..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.protocol.http.HttpDecoder; -import com.baidu.cloud.thirdparty.springframework.http.MediaType; -import com.baidu.cloud.thirdparty.springframework.http.converter.ByteArrayHttpMessageConverter; - -import java.util.Collections; - -/** - * Subclass of spring-mvc {@link com.baidu.cloud.thirdparty.springframework.http.converter.HttpMessageConverter}. Read - * body bytes from HttpMessage, but not change data format(not decode). - * - * @see ByteArrayHttpMessageConverter#readInternal The decode operation takes place in - * {@link HttpDecoder#decodeBody(MsgBase)} Created by liuruisen on 2020/6/8. - */ -public class BytesHttpMessageConverter extends ByteArrayHttpMessageConverter { - - public BytesHttpMessageConverter() { - setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); - } - - @Override - public boolean supports(Class clazz) { - return true; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolver.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolver.java deleted file mode 100644 index bd8c278f..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolver.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.QueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.Util; - -import java.util.Map; - -/** - * Build Http request that has request body by resolving args. Use method parameters to improve {@link RequestTemplate}. - * Resolve request body: serialize request body and set to http requestTemplate. - */ -public class EncodedRequestTemplateArgsResolver extends RequestTemplateArgsResolver { - - private Serializer encoder; - - public EncodedRequestTemplateArgsResolver(QueryMapEncoder queryMapEncoder, Target target, Serializer encoder) { - super(queryMapEncoder, target); - this.encoder = encoder; - } - - @Override - protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map variables, - MethodMetadata metadata) { - Object body = argv[metadata.bodyIndex()]; - Util.checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex()); - try { - mutable.body(encoder.serialize(body, metadata.bodyType()), Util.UTF_8); // serialize and set request body - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode request with SpringRestProtocol failed, BuildEncodedTemplateFromArgs failed: " - + e.getMessage()); - } - return super.resolve(argv, mutable, variables, metadata); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/FormRequestTemplateArgsResolver.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/FormRequestTemplateArgsResolver.java deleted file mode 100644 index 56982c81..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/FormRequestTemplateArgsResolver.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.QueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.Util; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import java.util.Map; - -/** - * form表单编码器 - */ -public class FormRequestTemplateArgsResolver extends RequestTemplateArgsResolver { - - private Serializer encoder = new JsonSerializer(); - - public FormRequestTemplateArgsResolver(QueryMapEncoder queryMapEncoder, Target target) { - super(queryMapEncoder, target); - } - - @Override - protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map variables, - MethodMetadata metadata) { - - Object body = argv[metadata.bodyIndex()]; - Util.checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex()); - try { - mutable.body(encoder.serialize(body, metadata.bodyType()), Util.UTF_8); // serialize and set request body - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode request with SpringRestProtocol failed, BuildEncodedTemplateFromArgs failed: " - + e.getMessage()); - } - return super.resolve(argv, mutable, variables, metadata); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptor.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptor.java deleted file mode 100644 index b6646ff3..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptor.java +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufInputStream; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.cookie.ServerCookieDecoder; -import com.baidu.cloud.thirdparty.springframework.util.CollectionUtils; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import com.baidu.cloud.thirdparty.servlet.AsyncContext; -import com.baidu.cloud.thirdparty.servlet.DispatcherType; -import com.baidu.cloud.thirdparty.servlet.RequestDispatcher; -import com.baidu.cloud.thirdparty.servlet.ServletContext; -import com.baidu.cloud.thirdparty.servlet.ServletException; -import com.baidu.cloud.thirdparty.servlet.ServletInputStream; -import com.baidu.cloud.thirdparty.servlet.ServletRequest; -import com.baidu.cloud.thirdparty.servlet.ServletResponse; -import com.baidu.cloud.thirdparty.servlet.http.Cookie; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletRequest; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; -import com.baidu.cloud.thirdparty.servlet.http.HttpSession; -import com.baidu.cloud.thirdparty.servlet.http.HttpUpgradeHandler; -import com.baidu.cloud.thirdparty.servlet.http.Part; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.InetSocketAddress; -import java.security.Principal; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -/** - * NettyServletRequestAdaptor Since Spring-mvc {@link RequestMappingHandlerMapping} handle with HttpServletRequest, so - * we convert {@link FullHttpRequest} to {@link HttpServletRequest}. Created by liuruisen on 2020/6/5. - */ -public class NettyServletRequestAdaptor implements HttpServletRequest { - - private FullHttpRequest nettyHttpRequest; - - private final String requestURI; - - private final String queryString; - - private final Map params; - - private final Map attributes; - - private final ByteBufServletInputStream inputStream; - - private Channel channel; - - private Locale locale; - - public NettyServletRequestAdaptor(FullHttpRequest fullHttpRequest, Channel channel) { - this(fullHttpRequest); - this.channel = channel; - this.locale = Locale.getDefault(); - } - - public NettyServletRequestAdaptor(FullHttpRequest fullHttpRequest) { - this.nettyHttpRequest = fullHttpRequest; - this.params = new ConcurrentHashMap<>(); - this.attributes = new ConcurrentHashMap<>(); - if (nettyHttpRequest.uri().contains("?")) { - String[] strs = nettyHttpRequest.uri().split("\\?"); - this.requestURI = strs[0]; - this.queryString = strs[1]; - } else { - this.requestURI = nettyHttpRequest.uri(); - this.queryString = null; - } - - if (!StringUtils.isBlank(queryString)) { - String[] paramsStrs = queryString.split("&"); - for (String paramStr : paramsStrs) { - String[] paramArr = paramStr.split("="); - String key = paramArr[0]; - String value = paramArr[1]; - if (this.params.get(key) == null) { - this.params.put(key, new String[] {value}); - } else { - List values = Arrays.asList(this.params.get(key)); - values.add(value); - String[] valueArr = new String[] {}; - values.toArray(valueArr); - params.put(key, valueArr); - } - } - } - - byte[] requestBytes = new byte[nettyHttpRequest.content().readableBytes()]; - nettyHttpRequest.content().readBytes(requestBytes); - inputStream = new ByteBufServletInputStream(new ByteBufInputStream(Unpooled.wrappedBuffer(requestBytes))); - } - - @Override - public String getAuthType() { - return null; - } - - @Override - public Cookie[] getCookies() { - String cookieString = nettyHttpRequest.headers().get(HttpHeaderNames.COOKIE); - if (!StringUtils.isBlank(cookieString)) { - Set cookieSet = - ServerCookieDecoder.LAX.decode(cookieString); - if (cookieSet != null && cookieSet.size() > 0) { - Cookie[] cookies = new Cookie[cookieSet.size()]; - int index = 0; - for (com.baidu.cloud.thirdparty.netty.handler.codec.http.cookie.Cookie nettyCookie : cookieSet) { - Cookie cookie = new Cookie(nettyCookie.name(), nettyCookie.value()); - cookie.setDomain(nettyCookie.domain() == null ? "" : nettyCookie.domain()); - cookie.setMaxAge((int) nettyCookie.maxAge()); - cookie.setPath(nettyCookie.path()); - cookie.setHttpOnly(nettyCookie.isHttpOnly()); - cookie.setSecure(nettyCookie.isSecure()); - cookies[index] = cookie; - index++; - } - return cookies; - } - } - return new Cookie[0]; - } - - @Override - public long getDateHeader(String name) { - return 0; - } - - @Override - public String getHeader(String name) { - return nettyHttpRequest.headers().get(name); - } - - @Override - public Enumeration getHeaders(String name) { - Iterator headersIterator = nettyHttpRequest.headers().getAll(name).iterator(); - return new Enumeration() { - @Override - public boolean hasMoreElements() { - return headersIterator.hasNext(); - } - - @Override - public String nextElement() { - return headersIterator.next(); - } - }; - } - - @Override - public Enumeration getHeaderNames() { - Iterator headerNamesIterator = nettyHttpRequest.headers().names().iterator(); - return new Enumeration() { - - @Override - public boolean hasMoreElements() { - return headerNamesIterator.hasNext(); - } - - @Override - public String nextElement() { - return headerNamesIterator.next(); - } - }; - } - - @Override - public int getIntHeader(String name) { - return Integer.parseInt(nettyHttpRequest.headers().get(name)); - } - - @Override - public String getMethod() { - return nettyHttpRequest.method().name(); - } - - @Override - public String getPathInfo() { - return null; - } - - @Override - public String getPathTranslated() { - return null; - } - - @Override - public String getContextPath() { - String requestURI = getRequestURI(); - return "/".equals(requestURI) ? "" : requestURI; - } - - @Override - public String getQueryString() { - return this.queryString; - } - - @Override - public String getRemoteUser() { - return null; - } - - @Override - public boolean isUserInRole(String role) { - return false; - } - - @Override - public Principal getUserPrincipal() { - return null; - } - - @Override - public String getRequestedSessionId() { - return null; - } - - @Override - public String getRequestURI() { - return this.requestURI; - } - - @Override - public StringBuffer getRequestURL() { - StringBuffer requestURLBuffer = new StringBuffer(); - requestURLBuffer.append(getScheme()); - requestURLBuffer.append("://"); - requestURLBuffer.append(getLocalAddr()); - requestURLBuffer.append(":"); - requestURLBuffer.append(getLocalPort()); - requestURLBuffer.append(getRequestURI()); - return requestURLBuffer; - } - - @Override - public String getServletPath() { - return this.requestURI; - } - - @Override - public HttpSession getSession(boolean create) { - return null; - } - - @Override - public HttpSession getSession() { - return null; - } - - @Override - public String changeSessionId() { - return null; - } - - @Override - public boolean isRequestedSessionIdValid() { - return false; - } - - @Override - public boolean isRequestedSessionIdFromCookie() { - return false; - } - - @Override - public boolean isRequestedSessionIdFromURL() { - return false; - } - - @Override - public boolean isRequestedSessionIdFromUrl() { - return false; - } - - @Override - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - return false; - } - - @Override - public void login(String username, String password) throws ServletException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor Not support login current"); - } - - @Override - public void logout() throws ServletException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor Not support logout current"); - } - - @Override - public Collection getParts() throws IOException, ServletException { // multipart/form-data - throw new UnsupportedOperationException("NettyServletRequestAdaptor Not support logout current"); - } - - @Override - public Part getPart(String name) throws IOException, ServletException { // multipart/form-data - throw new UnsupportedOperationException("NettyServletRequestAdaptor Not support logout current"); - } - - @Override - public T upgrade(Class handlerClass) throws IOException, ServletException { - // http1 upgrade to http2 - throw new UnsupportedOperationException("NettyServletRequestAdaptor Not support upgrade current"); - } - - @Override - public Object getAttribute(String name) { - return attributes.get(name); - } - - @Override - public Enumeration getAttributeNames() { - Iterator iterator = attributes.keySet().iterator(); - - return new Enumeration() { - @Override - public boolean hasMoreElements() { - return iterator.hasNext(); - } - - @Override - public String nextElement() { - return iterator.next(); - } - }; - } - - @Override - public String getCharacterEncoding() { - return "UTF-8"; - } - - @Override - public void setCharacterEncoding(String env) throws UnsupportedEncodingException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support set charset encoding"); - } - - @Override - public int getContentLength() { - return getIntHeader(HttpHeaderNames.CONTENT_LENGTH.toString()); - } - - @Override - public long getContentLengthLong() { - return getIntHeader(HttpHeaderNames.CONTENT_LENGTH.toString()); - } - - @Override - public String getContentType() { - return getHeader(HttpHeaderNames.CONTENT_TYPE.toString()); - } - - /** - * Wrapper request body bytebuf as {@link ByteBufServletInputStream} - * - * @return - * @throws IOException - * @see ByteBufServletInputStream - */ - @Override - public ServletInputStream getInputStream() throws IOException { - return inputStream; - } - - @Override - public String getParameter(String name) { - return this.params.get(name) == null ? null : this.params.get(name)[0]; - } - - @Override - public Enumeration getParameterNames() { - Iterator iterator = params.keySet().iterator(); - - return new Enumeration() { - @Override - public boolean hasMoreElements() { - return iterator.hasNext(); - } - - @Override - public String nextElement() { - return iterator.next(); - } - }; - } - - @Override - public String[] getParameterValues(String name) { - return this.params.get(name); - } - - @Override - public Map getParameterMap() { - return params; - } - - public void putAllParameterMap(Map paramMap) { - if (!CollectionUtils.isEmpty(paramMap)) { - this.params.putAll(paramMap); - } - } - - @Override - public String getProtocol() { - return nettyHttpRequest.protocolVersion().protocolName(); - } - - @Override - public String getScheme() { - return nettyHttpRequest.protocolVersion().protocolName().toLowerCase(); - } - - @Override - public String getServerName() { - return getRemoteHost(); - } - - @Override - public int getServerPort() { - return getRemotePort(); - } - - @Override - public BufferedReader getReader() throws IOException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support getReader"); - } - - @Override - public String getRemoteAddr() { - String remoteAddr = getHeader("X-Forwarded-For"); // proxy forward - if (StringUtils.isEmpty(remoteAddr)) { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getRemoteHost " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress(); - remoteAddr = insocket.getAddress().getHostAddress(); - } - return remoteAddr; - } - - @Override - public String getRemoteHost() { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getRemoteHost " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress(); - return insocket.getHostName(); - } - - @Override - public void setAttribute(String name, Object o) { - attributes.put(name, o); - } - - @Override - public void removeAttribute(String name) { - attributes.remove(name); - } - - @Override - public Locale getLocale() { - return locale; - } - - @Override - public Enumeration getLocales() { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support to getLocales"); - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public RequestDispatcher getRequestDispatcher(String path) { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support to getRequestDispatcher"); - } - - @Override - public String getRealPath(String path) { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support to getRealPath"); - } - - @Override - public int getRemotePort() { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getRemotePort " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress(); - return insocket.getPort(); - } - - @Override - public String getLocalName() { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getLocalName " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.localAddress(); - return insocket.getHostName(); - } - - @Override - public String getLocalAddr() { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getLocalAddr " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.localAddress(); - return insocket.getAddress().getHostAddress(); - } - - @Override - public int getLocalPort() { - if (channel == null) { - throw new UnsupportedOperationException( - "NettyServletRequestAdaptor not support to getLocalPort " + "without channel"); - } - InetSocketAddress insocket = (InetSocketAddress) channel.localAddress(); - return insocket.getPort(); - } - - @Override - public ServletContext getServletContext() { - return null; - } - - @Override - public AsyncContext startAsync() throws IllegalStateException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support to startAsync"); - } - - @Override - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) - throws IllegalStateException { - throw new UnsupportedOperationException("NettyServletRequestAdaptor not support to startAsync"); - } - - @Override - public boolean isAsyncStarted() { - return false; - } - - @Override - public boolean isAsyncSupported() { - return false; - } - - @Override - public AsyncContext getAsyncContext() { - return null; - } - - @Override - public DispatcherType getDispatcherType() { - return null; - } - - public FullHttpRequest getNettyHttpRequest() { - return nettyHttpRequest; - } - - public void setNettyHttpRequest(FullHttpRequest nettyHttpRequest) { - this.nettyHttpRequest = nettyHttpRequest; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptor.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptor.java deleted file mode 100644 index d6fe058d..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptor.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufOutputStream; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.cookie.DefaultCookie; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.cookie.ServerCookieEncoder; -import com.baidu.cloud.thirdparty.servlet.ServletException; -import com.baidu.cloud.thirdparty.servlet.ServletOutputStream; -import com.baidu.cloud.thirdparty.servlet.http.Cookie; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -/** - * NettyServletRequestAdaptor Since Spring-mvc {@link SpringRestHandlerMapping} handle with HttpServletRequest, so we - * convert {@link FullHttpResponse} to {@link HttpServletResponse}. Created by liuruisen on 2020/10/16. - */ -public class NettyServletResponseAdaptor implements HttpServletResponse { - - private NettyServletRequestAdaptor servletRequest; - - private FullHttpResponse nettyHttpResponse; - - private ByteBufServletOutputStream outputStream; - - private Locale locale; - - private boolean commited; - - private PrintWriter writer; - - public NettyServletResponseAdaptor(FullHttpResponse nettyHttpResponse, NettyServletRequestAdaptor servletRequest) { - this(nettyHttpResponse); - this.servletRequest = servletRequest; - } - - public NettyServletResponseAdaptor(FullHttpResponse nettyResponse) { - this.nettyHttpResponse = nettyResponse; - this.outputStream = new ByteBufServletOutputStream(new ByteBufOutputStream(nettyResponse.content())); - this.writer = new PrintWriter(outputStream); - this.locale = Locale.getDefault(); - } - - @Override - public void addCookie(Cookie cookie) { - DefaultCookie nettyCookie = new DefaultCookie(cookie.getName(), cookie.getValue()); - nettyCookie.setDomain(cookie.getDomain()); - nettyCookie.setMaxAge(cookie.getMaxAge()); - nettyCookie.setPath(cookie.getPath()); - nettyCookie.setHttpOnly(cookie.isHttpOnly()); - nettyCookie.setSecure(cookie.getSecure()); - String cookResult = ServerCookieEncoder.LAX.encode(nettyCookie); - nettyHttpResponse.headers().add(HttpHeaderNames.SET_COOKIE, cookResult); - } - - @Override - public boolean containsHeader(String headerKey) { - return nettyHttpResponse.headers().contains(headerKey); - } - - @Override - public String encodeURL(String url) { - try { - return URLEncoder.encode(url, getCharacterEncoding()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(new ServletException("Encoder URL failed", e)); - } - } - - @Override - public String encodeRedirectURL(String url) { - return this.encodeURL(url); - } - - @Override - public String encodeUrl(String url) { - return this.encodeURL(url); - } - - @Override - public String encodeRedirectUrl(String url) { - return this.encodeURL(url); - } - - @Override - public void sendError(int code, String msg) throws IOException { - if (msg != null) { - msg = msg.replace("\r", " "); - msg = msg.replace("\n", " "); - } - - this.nettyHttpResponse.setStatus(new HttpResponseStatus(code, msg)); - } - - @Override - public void sendError(int status) throws IOException { - // FIXME simple implement 需参考其他实现,是否有更优解 - this.nettyHttpResponse.setStatus(HttpResponseStatus.valueOf(status)); - } - - @Override - public void sendRedirect(String location) throws IOException { - // FIXME simple implement 需参考其他实现,是否有更优解 - setStatus(SC_FOUND); - setHeader(HttpHeaderNames.LOCATION.toString(), location); - } - - @Override - public void setDateHeader(String name, long date) { - this.nettyHttpResponse.headers().set(name, date); - } - - @Override - public void addDateHeader(String name, long date) { - this.nettyHttpResponse.headers().add(name, date); - } - - @Override - public void setHeader(String name, String value) { - this.nettyHttpResponse.headers().set(name, value); - } - - @Override - public void addHeader(String name, String value) { - this.nettyHttpResponse.headers().add(name, value); - } - - @Override - public void setIntHeader(String name, int value) { - this.nettyHttpResponse.headers().setInt(name, value); - } - - @Override - public void addIntHeader(String name, int value) { - this.nettyHttpResponse.headers().addInt(name, value); - } - - @Override - public void setStatus(int status) { - this.nettyHttpResponse.setStatus(HttpResponseStatus.valueOf(status)); - } - - @Override - public void setStatus(int status, String msg) { - this.nettyHttpResponse.setStatus(new HttpResponseStatus(status, msg)); - } - - @Override - public int getStatus() { - return nettyHttpResponse.status().code(); - } - - @Override - public String getHeader(String name) { - return nettyHttpResponse.headers().get(name); - } - - @Override - public Collection getHeaders(String name) { - return Arrays.asList(nettyHttpResponse.headers().get(name)); - } - - @Override - public Collection getHeaderNames() { - return nettyHttpResponse.headers().names(); - } - - @Override - public String getCharacterEncoding() { - String charset = nettyHttpResponse.headers().get(HttpHeaderNames.CONTENT_ENCODING); - return charset != null ? charset : "utf-8"; - } - - @Override - public String getContentType() { - return nettyHttpResponse.headers().get(HttpHeaderNames.CONTENT_TYPE); - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - return this.outputStream; - } - - @Override - public PrintWriter getWriter() throws IOException { - return this.writer; - } - - @Override - public void setCharacterEncoding(String charset) { - nettyHttpResponse.headers().set(HttpHeaderNames.CONTENT_ENCODING, charset); - } - - @Override - public void setContentLength(int contentLength) { - nettyHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, contentLength); - } - - @Override - public void setContentLengthLong(long contentLengthLong) { - nettyHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, contentLengthLong); - } - - @Override - public void setContentType(String contentType) { - nettyHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType); - } - - @Override - public void setBufferSize(int bufferSize) { - - } - - @Override - public int getBufferSize() { - return this.outputStream.getBufferSize(); - } - - @Override - public void flushBuffer() throws IOException { - this.getWriter().flush(); - this.commited = true; - } - - @Override - public void resetBuffer() { - this.outputStream.resetBuffer(); - } - - @Override - public boolean isCommitted() { - return commited; - } - - @Override - public void reset() { - if (isCommitted()) { - throw new IllegalStateException("Response already committed!"); - } - this.nettyHttpResponse.headers().clear(); - this.resetBuffer(); - } - - @Override - public void setLocale(Locale locale) { - this.locale = locale; - } - - @Override - public Locale getLocale() { - return locale; - } - - public FullHttpResponse getNettyHttpResponse() { - return nettyHttpResponse; - } - - public void setNettyHttpResponse(FullHttpResponse nettyHttpResponse) { - this.nettyHttpResponse = nettyHttpResponse; - } - - public NettyServletRequestAdaptor getServletRequest() { - return servletRequest; - } - - public void setServletRequest(NettyServletRequestAdaptor servletRequest) { - this.servletRequest = servletRequest; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolver.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolver.java deleted file mode 100644 index c1a1f503..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolver.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.Param; -import com.baidu.cloud.thirdparty.feign.QueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.Util; -import com.baidu.cloud.thirdparty.feign.codec.EncodeException; -import com.baidu.cloud.thirdparty.feign.template.UriUtils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Build {@link RequestTemplate} by resolving args. Use method parameters to improve {@link RequestTemplate}. Migrant - * from {@link com.baidu.cloud.thirdparty.feign.ReflectiveFeign}, because it's native scope is protected we can't call - * directly. - */ -public class RequestTemplateArgsResolver { - - // A QueryMapEncoder encodes Objects into maps of query parameter names to values. - private final QueryMapEncoder queryMapEncoder; - - // target service interface - protected final Target target; - - public RequestTemplateArgsResolver(QueryMapEncoder queryMapEncoder, Target target) { - this.target = target; - this.queryMapEncoder = queryMapEncoder; - - } - - public RequestTemplate create(Object[] argv, MethodMetadata metadata) { - RequestTemplate mutable = RequestTemplate.from(metadata.template()); - mutable.feignTarget(target); - if (metadata.urlIndex() != null) { - int urlIndex = metadata.urlIndex(); - Util.checkArgument(argv[urlIndex] != null, "URI parameter %s was null", urlIndex); - mutable.target(String.valueOf(argv[urlIndex])); - } - - Map indexToExpander = indexToExpander(metadata); - Map varBuilder = new LinkedHashMap(); - for (Map.Entry> entry : metadata.indexToName().entrySet()) { - int i = entry.getKey(); - Object value = argv[entry.getKey()]; - if (value != null) { // Null values are skipped. - if (indexToExpander.containsKey(i)) { - value = expandElements(indexToExpander.get(i), value); - } - for (String name : entry.getValue()) { - varBuilder.put(name, value); - } - } - } - // Resolve url: Resolve all expressions using the variable value substitutions provided. - RequestTemplate template = resolve(argv, mutable, varBuilder, metadata); - if (metadata.queryMapIndex() != null) { - // add query map parameters after initial resolve so that they take - // precedence over any predefined values - Object value = argv[metadata.queryMapIndex()]; - Map queryMap = toQueryMap(value); - template = addQueryMapQueryParameters(queryMap, template, metadata); - } - - if (metadata.headerMapIndex() != null) { - template = addHeaderMapHeaders((Map) argv[metadata.headerMapIndex()], template); - } - - return template; - } - - private Map indexToExpander(MethodMetadata metadata) { - Map indexToExpander = new LinkedHashMap(); - if (metadata.indexToExpander() != null) { - indexToExpander.putAll(metadata.indexToExpander()); - return indexToExpander; - } - if (metadata.indexToExpanderClass().isEmpty()) { - return indexToExpander; - } - for (Map.Entry> indexToExpanderClass : metadata.indexToExpanderClass() - .entrySet()) { - try { - indexToExpander.put(indexToExpanderClass.getKey(), indexToExpanderClass.getValue().newInstance()); - } catch (InstantiationException e) { - throw new IllegalStateException(e); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - return indexToExpander; - } - - private Map toQueryMap(Object value) { - if (value instanceof Map) { - return (Map) value; - } - try { - return queryMapEncoder.encode(value); - } catch (EncodeException e) { - throw new IllegalStateException(e); - } - } - - private Object expandElements(Param.Expander expander, Object value) { - if (value instanceof Iterable) { - return expandIterable(expander, (Iterable) value); - } - return expander.expand(value); - } - - private List expandIterable(Param.Expander expander, Iterable value) { - List values = new ArrayList(); - for (Object element : value) { - if (element != null) { - values.add(expander.expand(element)); - } - } - return values; - } - - @SuppressWarnings("unchecked") - private RequestTemplate addHeaderMapHeaders(Map headerMap, RequestTemplate mutable) { - for (Map.Entry currEntry : headerMap.entrySet()) { - Collection values = new ArrayList(); - - Object currValue = currEntry.getValue(); - if (currValue instanceof Iterable) { - Iterator iter = ((Iterable) currValue).iterator(); - while (iter.hasNext()) { - Object nextObject = iter.next(); - values.add(nextObject == null ? null : nextObject.toString()); - } - } else { - values.add(currValue == null ? null : currValue.toString()); - } - - mutable.header(currEntry.getKey(), values); - } - return mutable; - } - - @SuppressWarnings("unchecked") - private RequestTemplate addQueryMapQueryParameters(Map queryMap, RequestTemplate mutable, - MethodMetadata metadata) { - for (Map.Entry currEntry : queryMap.entrySet()) { - Collection values = new ArrayList(); - - boolean encoded = metadata.queryMapEncoded(); - Object currValue = currEntry.getValue(); - if (currValue instanceof Iterable) { - Iterator iter = ((Iterable) currValue).iterator(); - while (iter.hasNext()) { - Object nextObject = iter.next(); - if (nextObject == null) { - values.add(null); - } else { - values.add(encoded ? nextObject.toString() : UriUtils.encode(nextObject.toString())); - } - /* - * values.add(nextObject == null ? null : encoded ? nextObject.toString() : - * UriUtils.encode(nextObject.toString())); - */ - } - } else { - if (currValue == null) { - values.add(null); - } else { - values.add(encoded ? currValue.toString() : UriUtils.encode(currValue.toString())); - } - /* - * values.add(currValue == null ? null : encoded ? currValue.toString() : - * UriUtils.encode(currValue.toString())); - */ - } - - mutable.query(encoded ? currEntry.getKey() : UriUtils.encode(currEntry.getKey()), values); - } - return mutable; - } - - protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map variables, - MethodMetadata methodMetadata) { - return mutable.resolve(variables); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGenerator.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGenerator.java deleted file mode 100644 index 4c8d98b7..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGenerator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; - -/** - * Used to generate {@link RequestTemplate} when convert {@link RpcRequest} to Http request template. Composed of - * {@link MethodMetadata} and {@link RequestTemplateArgsResolver}. Will cached in {@link SpringRestHttpEncoder}. Created - * by liuruisen on 2020/6/3. - */ -public class RequestTemplateGenerator { - - /** - * Method metadata info, include method info, target class, http request metadata. Used to generate - * {@link RequestTemplate} and further generate Http Request. - */ - private final MethodMetadata methodMetadata; - - /** - * Use method parameters to improve {@link RequestTemplate}. - */ - private final RequestTemplateArgsResolver argsResolver; - - public RequestTemplateGenerator(MethodMetadata methodMetadata, RequestTemplateArgsResolver argsResolver) { - this.methodMetadata = methodMetadata; - this.argsResolver = argsResolver; - } - - public RequestTemplate create(Object[] args) { - return argsResolver.create(args, methodMetadata); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMapping.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMapping.java deleted file mode 100644 index 07db7a4a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMapping.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletRequest; -import com.baidu.cloud.thirdparty.servlet.http.HttpServletResponse; -import com.baidu.cloud.thirdparty.springframework.aop.support.AopUtils; -import com.baidu.cloud.thirdparty.springframework.core.DefaultParameterNameDiscoverer; -import com.baidu.cloud.thirdparty.springframework.core.MethodIntrospector; -import com.baidu.cloud.thirdparty.springframework.core.MethodParameter; -import com.baidu.cloud.thirdparty.springframework.core.ParameterNameDiscoverer; -import com.baidu.cloud.thirdparty.springframework.http.converter.HttpMessageConverter; -import com.baidu.cloud.thirdparty.springframework.http.converter.StringHttpMessageConverter; -import com.baidu.cloud.thirdparty.springframework.util.ClassUtils; -import com.baidu.cloud.thirdparty.springframework.web.bind.support.WebDataBinderFactory; -import com.baidu.cloud.thirdparty.springframework.web.context.request.NativeWebRequest; -import com.baidu.cloud.thirdparty.springframework.web.context.request.ServletWebRequest; -import com.baidu.cloud.thirdparty.springframework.web.method.HandlerMethod; -import com.baidu.cloud.thirdparty.springframework.web.method.support.HandlerMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.method.support.HandlerMethodArgumentResolverComposite; -import com.baidu.cloud.thirdparty.springframework.web.method.support.ModelAndViewContainer; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.RequestMappingInfo; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.method.annotation.RequestParamMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory; -import com.baidu.cloud.thirdparty.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * TODO 重复测试所有可能发生的情况 Extend spring-mvc {@link RequestMappingHandlerMapping} to convert HttpRequest to - * {@link RpcRequest}. - *
    - *
  • Step1: Store the mapping relationship between Method and RequestMappingInfo - * {@link #createMapping(Class, Object)}
  • - *
  • Step2: According to the mapping relationship, map HttpRequest to MethodHandler - * {@link #handler(HttpServletRequest)}
  • - *
  • Step3: Convert HttpRequst to method params - * {@link #resolveArguments(HandlerMethod, HttpServletRequest, HttpServletResponse)}
  • - *
- * Used in {@link SpringRestHttpDecoder}. - * - * @see SpringRestHttpDecoder#reverseConvertRequest Created by liuruisen on 2020/6/5. - */ -public class SpringRestHandlerMapping extends RequestMappingHandlerMapping { - - private static Logger logger = LoggerFactory.getLogger(SpringRestHandlerMapping.class); - - private static SpringRestHandlerMapping requestMappingHandlerMapping; - - private static final HandlerMethodArgumentResolverComposite ARGUMENT_RESOLVERS = - new HandlerMethodArgumentResolverComposite(); - - private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); - - private static final WebDataBinderFactory DATA_BINDER_FACTOR = new ServletRequestDataBinderFactory(null, null); - - private SpringRestHandlerMapping() {} - - public static SpringRestHandlerMapping getInstance() { - synchronized (SpringRestHandlerMapping.class) { - if (requestMappingHandlerMapping == null) { - requestMappingHandlerMapping = new SpringRestHandlerMapping(); - ARGUMENT_RESOLVERS.addResolvers(getDefaultArgumentResolvers()); - } - } - return requestMappingHandlerMapping; - } - - /** - * Called in the initialization phase to establish the mapping relationship. uri <-> Method - * - * @param serviceType - * @param serviceObj - */ - public void createMapping(Class serviceType, Object serviceObj) { - if (serviceType != null) { - Class userType = ClassUtils.getUserClass(serviceType); - Map methods = MethodIntrospector.selectMethods(userType, - (MethodIntrospector.MetadataLookup) method -> { - try { - return getMappingForMethod(method, userType); - } catch (Throwable ex) { - throw new IllegalStateException( - "Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); - } - }); - logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods); - methods.forEach((method, mapping) -> { - Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); - registerHandlerMethod(serviceObj, invocableMethod, mapping); - }); - } - } - - /** - * Get the target HandlerMethod mapping according to {@link HttpServletRequest} Since - * {@link RequestMappingHandlerMapping} is using {@link HttpServletRequest}, we also use - * - * @param request - * @return - */ - public HandlerMethod handler(HttpServletRequest request) throws Exception { - return getHandlerInternal(request); - } - - /** - * Extract parameters from {@link HttpServletRequest}. - * - * @param method - * @param request - * @param response - * @return param values for method - * @throws Exception - */ - public Object[] resolveArguments(HandlerMethod method, HttpServletRequest request, HttpServletResponse response) - throws Exception { - ServletWebRequest webRequest = new ServletWebRequest(request, response); - - return getMethodArgumentValues(webRequest, method); - } - - /** - * Get the method argument values for the current request. Migrant from spring-mvc - */ - private Object[] getMethodArgumentValues(NativeWebRequest request, HandlerMethod method) throws Exception { - - MethodParameter[] parameters = method.getMethodParameters(); - Object[] args = new Object[parameters.length]; - for (int i = 0; i < parameters.length; i++) { - MethodParameter parameter = parameters[i]; - parameter.initParameterNameDiscovery(SpringRestHandlerMapping.PARAMETER_NAME_DISCOVERER); - if (SpringRestHandlerMapping.ARGUMENT_RESOLVERS.supportsParameter(parameter)) { - try { - args[i] = SpringRestHandlerMapping.ARGUMENT_RESOLVERS.resolveArgument(parameter, - new ModelAndViewContainer(), request, DATA_BINDER_FACTOR); - continue; - } catch (Exception ex) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to resolve", ex); - } - throw ex; - } - } - if (args[i] == null) { - throw new IllegalStateException( - "Could not resolve method parameter at index " + parameter.getParameterIndex() + " in " - + parameter.getExecutable().toGenericString() + ": " + "No suitable resolver for"); - } - } - return args; - } - - /** - * Return the list of argument resolvers to use including built-in resolvers and custom resolvers provided via - * {@link #}. - */ - private static List getDefaultArgumentResolvers() { - List resolvers = new ArrayList<>(); - - // Annotation-based argument resolution - // @RequestParam - resolvers.add(new RequestParamMethodArgumentResolver(null, false)); - resolvers.add(new RequestParamMapMethodArgumentResolver()); // @RequestParam map - resolvers.add(new PathVariableMethodArgumentResolver()); // @PathVariable - resolvers.add(new PathVariableMapMethodArgumentResolver()); // @PathVariable map - resolvers.add(new MatrixVariableMethodArgumentResolver()); // @MatrixVariable (not support) - resolvers.add(new MatrixVariableMapMethodArgumentResolver()); // @MatrixVariable map (not support) - resolvers.add(new ServletModelAttributeMethodProcessor(false)); // @ModelAttribute nonessential - - StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); - stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316 - List> messageConverters = new ArrayList<>(2); - messageConverters.add(new BytesHttpMessageConverter()); - messageConverters.add(stringHttpMessageConverter); - - resolvers.add(new RequestResponseBodyMethodProcessor(messageConverters)); // @RequestBody - resolvers.add(new RequestPartMethodArgumentResolver(messageConverters)); // @RequestPart (not support) - resolvers.add(new RequestHeaderMethodArgumentResolver(null)); // @RequestHeader - resolvers.add(new RequestHeaderMapMethodArgumentResolver()); // @RequestHeader map - resolvers.add(new ServletCookieValueMethodArgumentResolver(null)); // - resolvers.add(new ExpressionValueMethodArgumentResolver(null)); - resolvers.add(new SessionAttributeMethodArgumentResolver()); - resolvers.add(new RequestAttributeMethodArgumentResolver()); // @RequestAttribute - - // servlet request and servlet response - resolvers.add(new ServletRequestMethodArgumentResolver()); - resolvers.add(new ServletResponseMethodArgumentResolver()); - - // Catch-all - resolvers.add(new RequestParamMethodArgumentResolver(null, true)); - return resolvers; - } - - /** - * Change the scope of the method to public - * - * @param method - * @param handlerType - * @return - */ - @Override - public RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { - Map requestMappingInfoHandlerMethodMap = getHandlerMethods(); - for (Map.Entry entry : requestMappingInfoHandlerMethodMap.entrySet()) { - if (entry.getValue().getMethod().equals(method)) { - return entry.getKey(); - } - } - return super.getMappingForMethod(method, handlerType); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoder.java deleted file mode 100644 index c8de03f3..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoder.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; -import com.baidu.cloud.starlight.protocol.http.HttpDecoder; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.servlet.ServletInputStream; -import com.baidu.cloud.thirdparty.springframework.http.HttpHeaders; -import com.baidu.cloud.thirdparty.springframework.http.converter.HttpMessageConversionException; -import com.baidu.cloud.thirdparty.springframework.web.method.HandlerMethod; - -import com.baidu.cloud.thirdparty.servlet.ServletException; -import com.baidu.cloud.thirdparty.springframework.web.servlet.NoHandlerFoundException; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Created by liuruisen on 2020/6/5. - */ -public class SpringRestHttpDecoder extends HttpDecoder { - - /** - * Convert httpRequest to Request: - *
    - *
  • step1: convert headers to kvMap, requestId
  • - *
  • step2: Get HandlerMethod map and resolve args
  • - *
- */ - @Override - protected Request reverseConvertRequest(FullHttpRequest httpRequest) { - long corelationId = Long.parseLong(httpRequest.headers().get(SpringRestProtocol.X_STARLIGHT_ID)); - Request request = new RpcRequest(corelationId); - request.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - request.setAttachmentKv(new HashMap<>()); - // store all request Headers to Request kv attachment - for (Map.Entry entry : httpRequest.headers().entries()) { - request.getAttachmentKv().put(entry.getKey(), entry.getValue()); - } - - Channel channel = ThreadLocalChannelContext.getContext().getChannel(); - // convert FullHttpRequest to HttpServletRequest - NettyServletRequestAdaptor servletRequestAdaptor = new NettyServletRequestAdaptor(httpRequest, channel); - - // form表单类型没有body的序列化器解码,需要在此解码 - String contentType = servletRequestAdaptor.getContentType(); - if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) { - String formBody = null; - try { - ServletInputStream inputStream = servletRequestAdaptor.getInputStream(); - byte[] contentBytes = new byte[inputStream.available()]; - inputStream.read(contentBytes); - formBody = new String(contentBytes, servletRequestAdaptor.getCharacterEncoding()); - } catch (IOException e) { - throw new CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - "Error occur when use SpringRestHttpDecoder to reverseConvertRequest: " + e.getMessage()); - } - - if (StringUtils.isNoneEmpty(formBody)) { - Map paramMap = resolveFromBody(formBody); - servletRequestAdaptor.putAllParameterMap(paramMap); - } - } - - // A response of the intermediate state, which will be replaced in the subsequent process - NettyServletResponseAdaptor servletResponseAdaptor = - new NettyServletResponseAdaptor(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.valueOf(AbstractHttpProtocol.UNKNOW_STATUS)), servletRequestAdaptor); - - // put servlet request and response to attachment, these will be put into RpcContext - // remember to remove when return response - // support servlet request - // 实现类似从Context中获取servlet的内容 - request.getAttachmentKv().put(Constants.SERVLET_REQUEST_KEY, servletRequestAdaptor); - request.getAttachmentKv().put(Constants.SERVLET_RESPONSE_KEY, servletResponseAdaptor); - - try { - // 请求映射 - SpringRestHandlerMapping handlerMapping = SpringRestHandlerMapping.getInstance(); - HandlerMethod handlerMethod = handlerMapping.handler(servletRequestAdaptor); - if (handlerMethod == null) { - throw new NoHandlerFoundException(servletRequestAdaptor.getMethod(), - servletRequestAdaptor.getRequestURI(), new HttpHeaders()); - } - - Class serviceClass = handlerMethod.getBeanType(); - if (serviceClass.getInterfaces().length > 0) { - serviceClass = serviceClass.getInterfaces()[0]; - } - request.setServiceName(serviceClass.getName()); // set serviceName - request.setMethodName(handlerMethod.getMethod().getName()); // set methodName - request.setParamsTypes(handlerMethod.getMethod().getParameterTypes()); // set paramsTypes - request.setGenericParamsTypes(handlerMethod.getMethod().getGenericParameterTypes()); - request.setMethod(handlerMethod.getMethod()); - // set service obj so we can use it without ServiceRegistry#discover - request.setServiceObj(handlerMethod.getBean()); - - // resolve param value: - // <1> if the param type is HttpServletRequest or HttpServletResponse, - // the value of it is NettyServletRequestAdapter or NettyServletResponseAdapter instance. - // @see ServletRequestMethodArgumentResolver ServletResponseMethodArgumentResolver - // <2> if the param type is others, the value of it is real object - // <3> if the param type is others and it behaves as @RequestBody, - // the param value will remain in byte form and wait for subsequent deserialization - // @see BytesHttpMessageConverter - Object[] args = - handlerMapping.resolveArguments(handlerMethod, servletRequestAdaptor, servletResponseAdaptor); - - request.setParams(args); // set params - - // sse协议 - boolean isSse = RpcSseEmitter.class.isAssignableFrom(request.getMethod().getReturnType()); - if (isSse) { - request.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - } - - return request; - } catch (Exception e) { - if (e instanceof ServletException || e instanceof HttpMessageConversionException) { - responseNotSupport(request, servletResponseAdaptor, channel, e.getMessage()); - // TODO 直接响应异常信息给客户端,思路是采取异常对象中封装response的方式 - throw new CodecException(CodecException.PROTOCOL_DECODE_EXCEPTION, - "Error occur when use SpringRestHttpDecoder to reverseConvertRequest: " + e.getMessage()); - } - if (e instanceof CodecException) { - throw (CodecException) e; - } - // if throw exception in convert procedure, we think can't use this protocol to decode(not match) - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Cannot not use SpringRestProtocol to decode request bytes"); - } finally { - // FIXME 多协议支持可能要移动位置 - if (httpRequest.refCnt() > 0) { - LOGGER.debug("Release httpRequest refCnt {}", httpRequest.refCnt()); - httpRequest.release(); - } - } - } - - /** - * 对于找不到handler映射、请求uri不支持的情况,直接响应不支持异常 - * - * @param request - * @param servletResponseAdaptor - * @param channel - * @param errorMsg - */ - private void responseNotSupport(Request request, NettyServletResponseAdaptor servletResponseAdaptor, - Channel channel, String errorMsg) { - // when handlerMethod is null, it means there is no handler in SpringRestProtocol, - // so we think decode error. - // FIXME Maybe it can be decoded with another HttpProtocol. - // FIXME Currently set to decode failure first, - // FIXME when multiple http protocols are implemented, please check if the logic here is as expected - - Response response = new RpcResponse(request.getId()); - response.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - response.setStatus(CodecException.PROTOCOL_DECODE_EXCEPTION); - response.setErrorMsg(errorMsg); - response.setRequest(request); - - try { - servletResponseAdaptor.setStatus(HttpResponseStatus.NOT_FOUND.code()); - - SpringRestHttpEncoder encoder = new SpringRestHttpEncoder(); - encoder.encodeBody(response); - - channel.writeAndFlush(response); - } catch (CodecException e) { - LOGGER.error("Error occur when return uri not support error to request, cause by {}", e.getMessage()); - } - } - - @Override - protected Response reverseConvertResponse(FullHttpResponse httpResponse) { - Response response = super.reverseConvertResponse(httpResponse); - if (response != null) { - response.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - } - return response; - } - - private Map resolveFromBody(String formBodyString) { - Map params = new HashMap<>(); - String[] paramsStrs = formBodyString.split("&"); - for (String paramStr : paramsStrs) { - String[] paramArr = paramStr.split("="); - String key = paramArr[0]; - String value = paramArr[1]; - if (params.get(key) == null) { - params.put(key, new String[] {value}); - } else { - List values = Arrays.asList(params.get(key)); - values.add(value); - String[] valueArr = new String[] {}; - values.toArray(valueArr); - params.put(key, valueArr); - } - } - - return params; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoder.java deleted file mode 100644 index dac2d097..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoder.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.protocol.http.HttpEncoder; -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; -import com.baidu.cloud.thirdparty.feign.Feign; -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.querymap.FieldQueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.spring.SpringContract; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpMessage; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderValues; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.springframework.http.MediaType; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.ModelAttribute; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.condition.ProducesRequestCondition; -import com.baidu.cloud.thirdparty.springframework.web.servlet.mvc.method.RequestMappingInfo; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; - -/** - * HttpDecoder that can encode {@link RpcRequest} to {@link FullHttpRequest} in accordance with spring-mvc annotation. - * Created by liuruisen on 2020/6/4. - */ -public class SpringRestHttpEncoder extends HttpEncoder { - - private static final SpringContract contract = new SpringContract(); - - private final Map requestTemplateGeneratorCache; - - private final Map, String> parsedServiceClass; - - public SpringRestHttpEncoder() { - this.requestTemplateGeneratorCache = new ConcurrentHashMap<>(); - this.parsedServiceClass = new ConcurrentHashMap<>(); - } - - /** - * Parse spring-mvc rest annotations. Convert {@link RpcRequest} to {@link FullHttpMessage}. Serialize body if has. - * - * @param rpcRequest - * @return - */ - @Override - protected FullHttpRequest convertRequest(Request rpcRequest) { - if (GenericUtil.isGenericCall(rpcRequest)) { - throw new StarlightRpcException(StarlightRpcException.BAD_REQUEST, - "SpringRest protocol not support generic call"); - } - - Class serviceClass = rpcRequest.getServiceClass(); - if (parsedServiceClass.get(serviceClass) == null) { // new service, parse and validate meta - parseAndValidateMeta(serviceClass); - } - - Method targetMethod = rpcRequest.getMethod(); - RequestTemplateGenerator generator = // Feign.configKey generate unique key for target method - requestTemplateGeneratorCache.get(Feign.configKey(serviceClass, targetMethod)); - if (generator == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode request with SpringRestProtocol failed: can not find parsed methodMeta, " + "maybe the method {" - + targetMethod.getName() + "} is illegal"); - } - - RequestTemplate template = generator.create(rpcRequest.getParams()); - return convert(template, rpcRequest); - } - - // TODO move to init logic 可能会有性能影响,考虑在初始化阶段进行解析存储 - - /** - * Parse and validate metadata(Annotations) on serviceClass. - * - * @param serviceClass - */ - private void parseAndValidateMeta(Class serviceClass) { - List methodMetadatas = contract.parseAndValidateMetadata(serviceClass); - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(SpringRestProtocol.PROTOCOL_NAME); - for (MethodMetadata metadata : methodMetadatas) { - RequestTemplateGenerator generator = null; - if (metadata.bodyIndex() != null) { - if (isFormData(metadata)) { - generator = new RequestTemplateGenerator(metadata, new FormRequestTemplateArgsResolver( - new FieldQueryMapEncoder(), Target.EmptyTarget.create(serviceClass))); - } else { - generator = new RequestTemplateGenerator(metadata, new EncodedRequestTemplateArgsResolver( - new FieldQueryMapEncoder(), Target.EmptyTarget.create(serviceClass), protocol.getSerialize())); - } - - } else { - generator = - new RequestTemplateGenerator(metadata, new RequestTemplateArgsResolver(new FieldQueryMapEncoder(), - Target.EmptyTarget.create(serviceClass))); - } - - requestTemplateGeneratorCache.put(metadata.configKey(), generator); - } - - parsedServiceClass.put(serviceClass, serviceClass.getSimpleName()); - } - - /** - * Use {@link RequestTemplate} to convert {@link Request} to {@link FullHttpRequest}. - * - * @param requestTemplate - * @return - */ - private FullHttpRequest convert(RequestTemplate requestTemplate, Request request) { - com.baidu.cloud.thirdparty.feign.Request feignRequest = requestTemplate.request(); - - FullHttpRequest httpRequest = null; - if (feignRequest.body() != null && feignRequest.body().length > 0) { - httpRequest = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(feignRequest.httpMethod().name()), - feignRequest.url(), Unpooled.wrappedBuffer(feignRequest.body())); - httpRequest.headers().add(HttpHeaderNames.CONTENT_TYPE, - SpringRestProtocol.CONTENT_TYPE_JSON + ";" + SpringRestProtocol.ENCODING); - httpRequest.headers().add(HttpHeaderNames.CONTENT_LENGTH, feignRequest.body().length); - } else { - httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, - HttpMethod.valueOf(feignRequest.httpMethod().name()), feignRequest.url()); - } - - // necessary header - httpRequest.headers().add(SpringRestProtocol.X_STARLIGHT_ID, request.getId()); - httpRequest.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); - - FullHttpRequest finalHttpRequest = httpRequest; - Function findRepeatHeaderFunc = (newHeaderKey) -> finalHttpRequest.headers().names().stream() - .filter(name -> StringUtils.equalsAnyIgnoreCase(name, newHeaderKey)).findAny().isPresent(); - - // request kvAttachment - if (request.getAttachmentKv() != null) { - for (Map.Entry kv : request.getAttachmentKv().entrySet()) { - if (kv.getKey() != null && kv.getValue() != null && !findRepeatHeaderFunc.apply(kv.getKey())) { - httpRequest.headers().add(kv.getKey(), kv.getValue()); - } - } - } - - // TODO 调研Netty对一个Header多个值的支持 - // feignRequest headers - if (feignRequest.headers().size() > 0) { - for (Map.Entry> header : feignRequest.headers().entrySet()) { - if (!findRepeatHeaderFunc.apply(header.getKey())) { - httpRequest.headers().add(header.getKey(), header.getValue()); - } - } - } - - return httpRequest; - } - - @Override - protected FullHttpResponse convertResponse(Response response) { - return super.convertResponse(response); - } - - @Override - protected void fulfillRpcResponse(FullHttpResponse httpResponse, Response response) { - - // clear - NettyServletRequestAdaptor servletRequestAdaptor = - (NettyServletRequestAdaptor) response.getRequest().getAttachmentKv().remove(Constants.SERVLET_REQUEST_KEY); - - // set content-type - httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType(servletRequestAdaptor, response)); - super.fulfillRpcResponse(httpResponse, response); - } - - private String contentType(NettyServletRequestAdaptor servletRequestAdaptor, Response response) { - SpringRestHandlerMapping handlerMapping = SpringRestHandlerMapping.getInstance(); - - // maybe decode error, such as not request uri is not found - if (response.getRequest().getMethod() == null) { - return HttpHeaderValues.APPLICATION_JSON.toString(); - } - - RequestMappingInfo requestMappingInfo = handlerMapping.getMappingForMethod(response.getRequest().getMethod(), - response.getRequest().getMethod().getDeclaringClass()); - // default value - if (requestMappingInfo == null) { - return HttpHeaderValues.APPLICATION_JSON.toString(); - } - - ProducesRequestCondition producesRequestCondition = - requestMappingInfo.getProducesCondition().getMatchingCondition(servletRequestAdaptor); - - if (producesRequestCondition != null && producesRequestCondition.getExpressions().size() > 0) { - MediaType contentMediaType = producesRequestCondition.getExpressions().iterator().next().getMediaType(); - return contentMediaType.toString(); - } else { // default is application/json - return HttpHeaderValues.APPLICATION_JSON.toString(); - } - } - - private boolean isFormData(MethodMetadata metadata) { - - Annotation[][] parameterAnnotations = metadata.method().getParameterAnnotations(); - if (parameterAnnotations != null) { - for (Annotation[] annotations : parameterAnnotations) { - if (annotations == null) { - continue; - } - for (Annotation annotation : annotations) { - boolean match = ModelAttribute.class.isAssignableFrom(annotation.getClass()); - if (match) { - return true; - } - } - } - } - return false; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocol.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocol.java deleted file mode 100644 index 585c3c8c..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocol.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; - -/** - * Allow developer to use spring rest annotation to develop Restful API. SpringRestProtocol will parse spring rest - * annotation metadata and convert method call to http request. SPI name: springrest TODO 尚未实现heartbeat Created by - * liuruisen on 2020/5/27. - */ -public class SpringRestProtocol extends AbstractHttpProtocol { - - public static final String PROTOCOL_NAME = "springrest"; - - private static final SpringRestHttpEncoder encoder = new SpringRestHttpEncoder(); - - private static final SpringRestHttpDecoder decoder = new SpringRestHttpDecoder(); - - @Override - public ProtocolEncoder getEncoder() { - return encoder; - } - - @Override - public ProtocolDecoder getDecoder() { - return decoder; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/HttpSseResponseDecoderAdaptor.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/HttpSseResponseDecoderAdaptor.java deleted file mode 100644 index 697b3b3b..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/HttpSseResponseDecoderAdaptor.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest.sse; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpDecoderConfig; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObjectAggregator; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseDecoder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; - -import static com.baidu.cloud.starlight.api.common.Constants.SUCCESS_CODE; - -/** - * 是为了解决以下问题而存在: sse请求的时候, server端可能返回成功响应,也可能错误响应 成功响应:是sse格式 错误响应:是普通的格式 - */ -public class HttpSseResponseDecoderAdaptor extends HttpResponseDecoder { - - private static final Logger LOGGER = LoggerFactory.getLogger(HttpSseResponseDecoderAdaptor.class); - - /** - * 512m - */ - private static final Integer MAX_CONTENT_LENGTH = 512 * 1024 * 1024; - - /** - * 20m 以及很大了 - */ - private static final Integer MAX_CHUNK_SIZE = 20 * 1024 * 1024; - - public HttpSseResponseDecoderAdaptor() { - // 注意这个参数设置:不允许返回不完整的chunk - super(new HttpDecoderConfig().setAllowPartialChunks(false).setMaxChunkSize(MAX_CHUNK_SIZE)); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { - super.decode(ctx, buffer, out); - // 检测到错误响应的话,直接解码出一个FullHttpResponse - if (!out.isEmpty() && out.get(0) instanceof HttpResponse) { - HttpResponse response = (HttpResponse) out.get(0); - if (response.getStatus().code() != SUCCESS_CODE) { - ctx.pipeline().addLast("aggregator", new HttpObjectAggregator(MAX_CONTENT_LENGTH)); - } - } - } - - /** - * 为什么要重写这个方法,是因为我们不想用 ByteToMessageDecoder 里面的 CUMULATOR 实现 starlight 有个特殊的ByteBuf可以实现 CUMULATOR 效果 - * - * @param ctx - * @param msg - * @throws Exception - */ - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof ByteBuf) { - List out = new LinkedList<>(); - try { - callDecode(ctx, (ByteBuf) msg, out); - } catch (Exception e) { - LOGGER.debug( - "Bytebuf cannot be decoded by http protocol, will retry another protocol. " + "the reason is : {}", - e.getMessage()); - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Bytebuf cannot be decoded by http protocol, will retry another protocol. " + "The reason is " - + e.getMessage()); - } finally { - for (Object result : out) { - ctx.fireChannelRead(result); - } - } - } else { - ctx.fireChannelRead(msg); - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpDecoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpDecoder.java deleted file mode 100644 index 3ab020b6..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpDecoder.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest.sse; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; -import com.baidu.cloud.starlight.protocol.http.springrest.SpringRestHttpDecoder; -import com.baidu.cloud.thirdparty.apache.commons.lang3.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObject; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.LastHttpContent; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static com.baidu.cloud.starlight.api.common.Constants.SSE_EMBEDDED_CHANNEL_KEY; -import static com.baidu.cloud.starlight.api.common.Constants.SSE_REQUEST_ID_KEY; -import static com.baidu.cloud.starlight.api.common.Constants.SUCCESS_CODE; - -public class SpringRestSseHttpDecoder extends SpringRestHttpDecoder { - private static final byte[] DEFAULT_BODY = new byte[] {0}; - - @Override - public MsgBase decode(DynamicCompositeByteBuf input) throws CodecException { - ChannelAttribute channelAttribute = ThreadLocalChannelContext.getContext().getChannelAttribute(); - ChannelSide channelSide = channelAttribute.getRpcChannel().side(); - - // 服务端完整解包request - if (channelSide == ChannelSide.SERVER) { - return super.decode(input); - } - - // 客户端侧在发送请求的时候在channelAttribute设置了sse协议,所以如果不是sse协议,那就跳过,避免误解其他协议的response包 - if (!StringUtils.equalsIgnoreCase(channelAttribute.getChannelProtocol(), SpringRestSseProtocol.PROTOCOL_NAME)) { - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "channelAttribute#getChannelProtocol not springrestsse"); - } - - // sse客户端的 response 解码进行适配 - RpcChannel rpcChannel = channelAttribute.getRpcChannel(); - // 获取跟channel绑定的 embeddedChannel - EmbeddedChannel embeddedChannel = (EmbeddedChannel) rpcChannel.getAttribute(SSE_EMBEDDED_CHANNEL_KEY); - if (embeddedChannel == null) { - embeddedChannel = new EmbeddedChannel(new HttpSseResponseDecoderAdaptor()); - rpcChannel.setAttribute(SSE_EMBEDDED_CHANNEL_KEY, embeddedChannel); - } - - ByteBuf byteBuf = input.retainedSlice(input.readableBytes()); - ByteBuf byteBufCopy = byteBuf.copy(); - boolean decodeFail = false; - try { - embeddedChannel.writeInbound(byteBufCopy); - if (embeddedChannel.inboundMessages().isEmpty()) { - // 解不出来一个包 返回空,等数据来了再试 - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTENOUGHDATA_EXCEPTION, - "Data not enough to parse using sse"); - } - - List httpObjects = - embeddedChannel.inboundMessages().stream().map(o -> (HttpObject) o).collect(Collectors.toList()); - // 读取完之后,记得清空,不然影响下次读取 - embeddedChannel.inboundMessages().clear(); - - decodeFail = httpObjects.stream().filter(e -> !e.getDecoderResult().isSuccess()).findAny().isPresent(); - if (decodeFail) { - LOGGER.debug("Cannot use Http sse protocol to decode: decoded result is null or failed"); - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Cannot use Http sse protocol to decode: decoded result is null"); - } - - // 如果是错误响应 ,解包出来的是一个 FullHttpResponse - if (httpObjects.size() == 1 && httpObjects.get(0) instanceof FullHttpResponse) { - Response response = reverseConvertResponse((FullHttpResponse) httpObjects.get(0)); - if (response != null) { - response.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - } - return response; - } - - Response response; - long corelationId = -1; - if (httpObjects.get(0) instanceof HttpResponse) { - HttpResponse httpResponse = (HttpResponse) httpObjects.get(0); - if (httpResponse.headers().get(AbstractHttpProtocol.X_STARLIGHT_ID) != null) { - corelationId = Long.parseLong(httpResponse.headers().get(AbstractHttpProtocol.X_STARLIGHT_ID)); - rpcChannel.setAttribute(SSE_REQUEST_ID_KEY, corelationId); - } - response = new RpcResponse(corelationId); - // set attachmentKv - response.setAttachmentKv(new HashMap<>()); - for (Map.Entry entry : httpResponse.headers().entries()) { - response.getAttachmentKv().put(entry.getKey(), entry.getValue()); - } - } else { - corelationId = (long) rpcChannel.getAttribute(SSE_REQUEST_ID_KEY); - response = new RpcResponse(corelationId); - } - - response.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - response.setStatus(SUCCESS_CODE); - response.setResult(httpObjects); - response.setBodyBytes(DEFAULT_BODY); - return response; - } finally { - if (!decodeFail) { - input.skipBytes(byteBufCopy.readerIndex()); - } - byteBuf.release(); - } - } - - @Override - protected void decodeResponseBody(Response response) { - // 处理异常情况 - if (response.getStatus() != SUCCESS_CODE) { - super.decodeResponseBody(response); - return; - } - - response.setProtocolName(SpringRestSseProtocol.PROTOCOL_NAME); - List httpObjects = (List) response.getResult(); - - List serverEvents = new ArrayList<>(); - - for (HttpObject httpObject : httpObjects) { - if (httpObject instanceof HttpResponse) { - serverEvents.add(ServerEvent.START_EVENT); - } else if (httpObject instanceof LastHttpContent) { - serverEvents.add(ServerEvent.COMPLETE_EVENT); - } else if (httpObject instanceof HttpContent) { - serverEvents.add(decodeServerEvent((HttpContent) httpObject)); - } else { - throw new IllegalStateException("unsupported httpObject :" + httpObject); - } - } - response.setResult(serverEvents); - } - - private ServerEvent decodeServerEvent(HttpContent httpContent) { - ServerEvent serverEvent = new ServerEvent(); - String content = httpContent.content().toString(StandardCharsets.UTF_8); - String[] lines = content.split("\n"); - - StringBuffer dataBuffer = new StringBuffer(); - for (String line : lines) { - if (line.startsWith(":")) { - serverEvent.setComment(line.replaceFirst(":", "")); - } else if (line.startsWith("id:")) { - serverEvent.setId(line.replaceFirst("id:", "")); - } else if (line.startsWith("event:")) { - serverEvent.setEvent(line.replaceFirst("event:", "")); - } else if (line.startsWith("retry:")) { - serverEvent.setRetry(Long.parseLong(line.replaceFirst("retry:", "").trim())); - } else if (line.startsWith("data:")) { - dataBuffer.append(line.replaceFirst("data:", "")); - } - } - - serverEvent.setData(dataBuffer.toString()); - return serverEvent; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpEncoder.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpEncoder.java deleted file mode 100644 index 0a835f0e..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseHttpEncoder.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest.sse; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.ShuttingDownEvent; -import com.baidu.cloud.starlight.api.rpc.sse.RpcSseEmitter; -import com.baidu.cloud.starlight.api.rpc.sse.ServerEvent; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; -import com.baidu.cloud.starlight.protocol.http.springrest.SpringRestHttpEncoder; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultLastHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObject; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.LastHttpContent; - -import java.nio.charset.StandardCharsets; - -import static com.baidu.cloud.starlight.api.common.Constants.SSE_EMBEDDED_CHANNEL_KEY; - -public class SpringRestSseHttpEncoder extends SpringRestHttpEncoder { - - @Override - protected void encodeResponseBody(Response response) { - // 如果是异常响应,则走原本的逻辑即可 - if (response.getStatus() != Constants.SUCCESS_CODE) { - super.encodeResponseBody(response); - } else { - // 如果是sse正常响应 - Object result = response.getResult(); - if (result instanceof ServerEvent) { - if (result == ServerEvent.START_EVENT) { - HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/event-stream;charset=UTF-8"); - httpResponse.headers().set(HttpHeaderNames.CACHE_CONTROL, "no-cache"); - httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive"); - httpResponse.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "chunked"); - // request-id - httpResponse.headers().set(AbstractHttpProtocol.X_STARLIGHT_ID, response.getId()); - // 适配零信任网关SSE逻辑,参考文档:https://ku.baidu-int.com/knowledge/HFVrC7hq1Q/b_dB7xLNHi/yToZib1hj4/hZlgASbuCxSw11 - httpResponse.headers().set("X-Accel-Buffering", "no"); - - response.setResult(httpResponse); - } else if (result == ServerEvent.COMPLETE_EVENT) { - LastHttpContent lastHttpContent = new DefaultLastHttpContent(); - - response.setResult(lastHttpContent); - } else { - ServerEvent serverEvent = (ServerEvent) result; - ByteBuf byteBuf = Unpooled.wrappedBuffer(serverEvent.toData().getBytes(StandardCharsets.UTF_8)); - HttpContent httpContent = new DefaultHttpContent(byteBuf); - - response.setResult(httpContent); - } - } else if (result instanceof ShuttingDownEvent) { - // TODO 暂时没有想到好的办法处理它 - } - } - } - - @Override - protected ByteBuf encodeResponse(Response response) { - - if (response.getResult() == null || !(response.getResult() instanceof HttpObject)) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "RpcResponse have not been converted to HttpObject, please check"); - } - - HttpObject httpObject = (HttpObject) response.getResult(); - - RpcChannel rpcChannel = ThreadLocalChannelContext.getContext().getChannelAttribute().getRpcChannel(); - // 获取跟channel绑定的 embeddedChannel - EmbeddedChannel embeddedChannel = (EmbeddedChannel) rpcChannel.getAttribute(SSE_EMBEDDED_CHANNEL_KEY); - if (embeddedChannel == null) { - embeddedChannel = new EmbeddedChannel(new HttpResponseEncoder()); - rpcChannel.setAttribute(SSE_EMBEDDED_CHANNEL_KEY, embeddedChannel); - } - - try { - embeddedChannel.writeOutbound(httpObject); - - ByteBuf[] outputBufs = new ByteBuf[embeddedChannel.outboundMessages().size()]; - embeddedChannel.outboundMessages().toArray(outputBufs); - - // 读一次清空一次 - embeddedChannel.outboundMessages().clear(); - return Unpooled.wrappedBuffer(outputBufs); - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Encode Response to ByteBuf failed: " + e.getMessage()); - } - - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocol.java b/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocol.java deleted file mode 100644 index 1d4a469b..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocol.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest.sse; - -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.protocol.http.springrest.SpringRestProtocol; - -public class SpringRestSseProtocol extends SpringRestProtocol { - - public static final String PROTOCOL_NAME = "springrestsse"; - - private static final SpringRestSseHttpEncoder ENCODER = new SpringRestSseHttpEncoder(); - - private static final SpringRestSseHttpDecoder DECODER = new SpringRestSseHttpDecoder(); - - @Override - public ProtocolEncoder getEncoder() { - return ENCODER; - } - - @Override - public ProtocolDecoder getDecoder() { - return DECODER; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol b/starlight/starlight-protocol/starlight-protocol-http/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol deleted file mode 100644 index ad401d70..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol +++ /dev/null @@ -1,2 +0,0 @@ -com.baidu.cloud.starlight.protocol.http.springrest.SpringRestProtocol -com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocolTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocolTest.java deleted file mode 100644 index 817fe0d6..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/AbstractHttpProtocolTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class AbstractHttpProtocolTest { - - private AbstractHttpProtocol protocol = new AbstractHttpProtocol() { - @Override - public ProtocolEncoder getEncoder() { - return new HttpEncoder() { - @Override - protected FullHttpRequest convertRequest(Request rpcRequest) { - return null; - } - }; - } - - @Override - public ProtocolDecoder getDecoder() { - return new HttpDecoder() { - @Override - protected Request reverseConvertRequest(FullHttpRequest httpRequest) { - return null; - } - }; - } - }; - - @Test - public void getEncoder() { - assertTrue(protocol.getEncoder() instanceof HttpEncoder); - } - - @Test - public void getDecoder() { - assertTrue(protocol.getDecoder() instanceof HttpDecoder); - } - - @Test - public void getHeartbeatTrigger() { - assertTrue(protocol.getHeartbeatTrigger() == null); - } - - @Test - public void getSerialize() { - assertTrue(protocol.getSerialize() instanceof JsonSerializer); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpDecoderTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpDecoderTest.java deleted file mode 100644 index 96c5a122..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpDecoderTest.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import org.junit.Test; - -import static com.baidu.cloud.starlight.api.exception.CodecException.BODY_DECODE_EXCEPTION; -import static com.baidu.cloud.starlight.api.exception.CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class HttpDecoderTest { - - private HttpDecoder decoder = new HttpDecoder() { - @Override - protected Request reverseConvertRequest(FullHttpRequest httpRequest) { - return null; - } - }; - private HttpEncoder encoder = new HttpEncoder() { - @Override - protected FullHttpRequest convertRequest(Request rpcRequest) { - return null; - } - }; - - @Test - public void decodeRequest() { - // decode request - FullHttpRequest httpRequest = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5"); - httpRequest.headers().add("Operator", "Add"); - httpRequest.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, "1"); - - Request request = new RpcRequest(); - request.setParams(new Object[] {httpRequest}); - ByteBuf byteBuf = encoder.encode(request); - - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - compositeByteBuf.addBuffer(byteBuf); - MsgBase msgBase = decoder.decode(compositeByteBuf); - assertNull(msgBase); - } - - @Test - public void decodeResponse() { - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - // decode response - JsonSerializer serializer = new JsonSerializer(); - User user = new User(); - user.setUserId(1); - user.setName("312313"); - ByteBuf content = Unpooled.wrappedBuffer(serializer.serialize(user, User.class)); - - // normal response - FullHttpResponse httpResponse = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); - httpResponse.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, "1"); - httpResponse.headers().add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); - httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, "application/json"); - - Response response = new RpcResponse(); - response.setResult(httpResponse); - ByteBuf byteBuf2 = encoder.encode(response); - compositeByteBuf.addBuffer(byteBuf2); - MsgBase msgBase2 = decoder.decode(compositeByteBuf); - assertTrue(msgBase2 != null); - assertTrue(msgBase2.getId() == 1); - assertTrue(msgBase2 instanceof Response); - assertTrue(((Response) msgBase2).getStatus() == HttpResponseStatus.OK.code()); - } - - @Test - public void decodeErrorResponse() { - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - // abnormal response - FullHttpResponse errorResponse = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); - errorResponse.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, "1"); - errorResponse.headers().add(HttpHeaderNames.CONTENT_LENGTH, 0); - // errorResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, "application/json"); - - Response response1 = new RpcResponse(); - response1.setResult(errorResponse); - ByteBuf byteBuf = encoder.encode(response1); - compositeByteBuf.addBuffer(byteBuf); - MsgBase msgBase = decoder.decode(compositeByteBuf); - assertTrue(msgBase instanceof Response); - assertTrue(((Response) msgBase).getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR.code()); - } - - @Test - public void decodeNull() { - // input bytebuf is null - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - try { - decoder.decode(compositeByteBuf); - } catch (CodecException e) { - assertEquals(e.getCode(), PROTOCOL_INSUFFICIENT_DATA_EXCEPTION); - } - - // request id is null - FullHttpRequest httpRequest = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5"); - httpRequest.headers().add("Operator", "Add"); - Request request = new RpcRequest(); - request.setParams(new Object[] {httpRequest}); - ByteBuf byteBuf = encoder.encode(request); - compositeByteBuf.addBuffer(byteBuf); - decoder.decode(compositeByteBuf); - assertEquals(0, compositeByteBuf.readableBytes()); - - // content-type is not support - FullHttpRequest httpRequest1 = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5"); - httpRequest1.headers().add("Operator", "Add"); - httpRequest1.headers().add(HttpHeaderNames.CONTENT_TYPE, "test/test"); - httpRequest1.headers().add(AbstractHttpProtocol.X_STARLIGHT_ID, "1"); - Request request1 = new RpcRequest(); - request1.setParams(new Object[] {httpRequest1}); - compositeByteBuf.addBuffer(encoder.encode(request1)); - decoder.decode(compositeByteBuf); - - assertEquals(compositeByteBuf.readableBytes(), 0); - } - - @Test - public void decodeRequestBody() { - User user = new User(); - user.setName("name"); - user.setUserId(123); - byte[] bytes = new JsonSerializer().serialize(user, User.class); - - // decode request with body bytes - Request request = new RpcRequest(1); - request.setProtocolName("springrest"); - request.setParamsTypes(new Class[] {User.class}); - request.setParams(new Object[] {bytes}); - request.setGenericParamsTypes(new Class[] {User.class}); - decoder.decodeBody(request); - assertTrue(request.getParams().length == 1); - assertEquals(((User) request.getParams()[0]).getName(), "name"); - - // decode request without params - Request request2 = new RpcRequest(1); - request2.setProtocolName("springrest"); - decoder.decodeBody(request2); - assertTrue(request2.getParams() == null); - - // decode request without bytes params - Request request3 = new RpcRequest(1); - request3.setProtocolName("springrest"); - request3.setParamsTypes(new Class[] {String.class}); - request3.setParams(new Object[] {"test"}); - decoder.decodeBody(request3); - assertTrue(request3.getParams().length == 1); - assertEquals(((String) request3.getParams()[0]), "test"); - } - - @Test - public void decodeResponseBody() { - User user = new User(); - user.setName("name"); - user.setUserId(123); - byte[] bytes = new JsonSerializer().serialize(user, User.class); - - // decode response body, null body byets - Response response = new RpcResponse(1); - response.setProtocolName("springrest"); - decoder.decodeBody(response); - - // decode response body, error body bytes - response.setStatus(500); - response.setBodyBytes(new JsonSerializer().serialize("Error", String.class)); - decoder.decodeBody(response); - assertTrue(response.getErrorMsg().equals("Error")); - - // decode response body, Success - response.setStatus(200); - response.setBodyBytes(bytes); - response.setReturnType(User.class); - response.setGenericReturnType(User.class); - decoder.decodeBody(response); - assertTrue(response.getResult() != null); - assertTrue(response.getResult() instanceof User); - } - - @Test - public void decodeResponseBodyError() { - - // decode null - try { - decoder.decodeBody(null); - } catch (CodecException e) { - assertEquals(e.getCode(), BODY_DECODE_EXCEPTION); - } - - // decode without ReturnType - User user = new User(); - user.setName("name"); - user.setUserId(123); - byte[] bytes = new JsonSerializer().serialize(user, User.class); - Response response = new RpcResponse(1); - response.setProtocolName("springrest"); - response.setStatus(200); - response.setBodyBytes(bytes); - try { - decoder.decodeBody(response); - } catch (CodecException e) { - assertEquals(e.getCode(), BODY_DECODE_EXCEPTION); - } - - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpEncoderTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpEncoderTest.java deleted file mode 100644 index 3a555367..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpEncoderTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.AbstractMsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import org.junit.Test; - -import java.util.Collections; - -import static com.baidu.cloud.starlight.api.exception.CodecException.BODY_ENCODE_EXCEPTION; -import static com.baidu.cloud.starlight.api.exception.CodecException.PROTOCOL_ENCODE_EXCEPTION; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class HttpEncoderTest { - - private HttpEncoder httpEncoder = new HttpEncoder() { - @Override - protected FullHttpRequest convertRequest(Request rpcRequest) { - return null; - } - }; - - @Test - public void encode() { - // encode request - FullHttpRequest httpRequest = - new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5"); - httpRequest.headers().add("Operator", "Add"); - - Request request = new RpcRequest(); - request.setParams(new Object[] {httpRequest}); - ByteBuf byteBuf = httpEncoder.encode(request); - - assertTrue(byteBuf != null); - assertTrue(byteBuf.readableBytes() > 0); - - // encode response - FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - Response response = new RpcResponse(); - response.setResult(httpResponse); - ByteBuf byteBuf2 = httpEncoder.encode(response); - assertTrue(byteBuf2 != null); - assertTrue(byteBuf2.readableBytes() > 0); - } - - @Test - public void echoNull() { - // input == null - try { - httpEncoder.encode(null); - } catch (CodecException e) { - assertEquals(e.getCode(), PROTOCOL_ENCODE_EXCEPTION); - } - - // request params null - try { - httpEncoder.encode(new RpcRequest()); - } catch (CodecException e) { - assertEquals(e.getCode(), PROTOCOL_ENCODE_EXCEPTION); - } - - // response params null - try { - httpEncoder.encode(new RpcResponse()); - } catch (CodecException e) { - assertEquals(e.getCode(), PROTOCOL_ENCODE_EXCEPTION); - } - - // msgBase neither Request nor Response - try { - httpEncoder.encode(new AbstractMsgBase() { - @Override - public long getId() { - return super.getId(); - } - }); - } catch (CodecException e) { - assertEquals(e.getCode(), PROTOCOL_ENCODE_EXCEPTION); - } - } - - @Test - public void encodeBody() { - // encode requestBody - Request request = new RpcRequest(); - httpEncoder.encodeBody(request); - assertEquals(request.getParams().length, 1); - assertNull(request.getParams()[0]); - - // encode response body -- error - Response response = new RpcResponse(123); - response.setProtocolName("springrest"); - response.setStatus(500); - response.setErrorMsg("Error 500"); - response.setAttachmentKv(Collections.singletonMap("test", 123)); - httpEncoder.encodeBody(response); - assertNotNull(response.getResult()); - assertTrue(response.getResult() instanceof FullHttpResponse); - FullHttpResponse httpResponse = (FullHttpResponse) response.getResult(); - assertTrue(httpResponse.content().readableBytes() > 0); - JsonSerializer jsonSerializer = new JsonSerializer(); - byte[] errorBytes = jsonSerializer.serialize("Error 500", String.class); - assertTrue(httpResponse.content().readableBytes() == errorBytes.length); - - // encode response body -- success - Response response1 = new RpcResponse(123); - response1.setProtocolName("springrest"); - response1.setStatus(200); - response1.setResult("Success 200"); - response1.setRequest(request); - httpEncoder.encodeBody(response1); - assertNotNull(response1.getResult()); - assertTrue(response1.getResult() instanceof FullHttpResponse); - FullHttpResponse httpResponse1 = (FullHttpResponse) response1.getResult(); - assertTrue(httpResponse1.content().readableBytes() > 0); - byte[] responseBytes = new byte[httpResponse1.content().readableBytes()]; - httpResponse1.content().readBytes(responseBytes); - String resultStr = (String) new JsonSerializer().deserialize(responseBytes, String.class); - assertEquals(resultStr, "Success 200"); - } - - @Test - public void encodeBodyNull() { - try { - httpEncoder.encodeBody(null); - } catch (CodecException e) { - assertEquals(e.getCode(), BODY_ENCODE_EXCEPTION); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoderTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoderTest.java deleted file mode 100644 index 3c5de058..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/HttpRequestResponseDecoderTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.CompositeByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.buffer.UnpooledByteBufAllocator; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderValues; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMessage; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import org.junit.Assert; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.Queue; - -/** - * Created by liuruisen on 2020/6/2. - */ -public class HttpRequestResponseDecoderTest { - - private HttpRequestResponseDecoder requestResponseDecoder = new HttpRequestResponseDecoder(); - - @Test - public void createMessage() throws Exception { - String[] responseInitLines = new String[] {"HTTP/1.1", "200", "OK"}; - HttpMessage httpMessage = requestResponseDecoder.createMessage(responseInitLines); - - Assert.assertTrue(httpMessage instanceof HttpResponse); - Assert.assertTrue(((DefaultHttpResponse) httpMessage).status().code() == 200); - Assert.assertFalse(requestResponseDecoder.isDecodingRequest()); - - String[] requestInitLines = new String[] {"GET", "/echo", "HTTP/1.1"}; - HttpMessage httpMessage2 = requestResponseDecoder.createMessage(requestInitLines); - Assert.assertTrue(httpMessage2 instanceof HttpRequest); - Assert.assertTrue(((DefaultHttpRequest) httpMessage2).method().name().equals("GET")); - Assert.assertTrue(requestResponseDecoder.isDecodingRequest()); - } - - @Test - public void createInvalidMessage() throws Exception { - // response - String[] responseInitLines = new String[] {"HTTP/1.1", "200", "OK"}; - requestResponseDecoder.createMessage(responseInitLines); - - HttpMessage httpMessage = requestResponseDecoder.createInvalidMessage(); - Assert.assertTrue(httpMessage instanceof HttpResponse); - Assert.assertTrue(((DefaultHttpResponse) httpMessage).status().code() == 999); - - // request - String[] requestInitLines = new String[] {"GET", "/echo", "HTTP/1.1"}; - requestResponseDecoder.createMessage(requestInitLines); - - HttpMessage httpMessage2 = requestResponseDecoder.createInvalidMessage(); - Assert.assertTrue(httpMessage2 instanceof HttpRequest); - Assert.assertTrue(((DefaultHttpRequest) httpMessage2).method().name().equals("GET")); - } - - @Test - public void testDecodeResponse1() { - // 模拟两个response数据包 粘在一起 - ByteBuf data1 = Unpooled.wrappedBuffer("response1".getBytes(StandardCharsets.UTF_8)); - DefaultFullHttpResponse response1 = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, data1); - response1.headers().add("Content-Length", data1.readableBytes()); - - ByteBuf data2 = Unpooled.wrappedBuffer("response1".getBytes(StandardCharsets.UTF_8)); - DefaultFullHttpResponse response2 = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, data2); - response2.headers().add("Content-Length", data2.readableBytes()); - - EmbeddedChannel outboundChannel = new EmbeddedChannel(new HttpResponseEncoder()); - outboundChannel.writeOutbound(response1, response2); - - CompositeByteBuf outboundByteBuf = Unpooled.compositeBuffer(); - for (Object msg : outboundChannel.outboundMessages()) { - outboundByteBuf.addComponent(true, (ByteBuf) msg); - } - // -- 模拟完毕 - - EmbeddedChannel inboundChannel = new EmbeddedChannel(new HttpRequestResponseDecoder()); - - inboundChannel.writeInbound(outboundByteBuf); - Queue inboundMessages = inboundChannel.inboundMessages(); - Assert.assertTrue(inboundMessages.size() == 1); - - inboundChannel.writeInbound(outboundByteBuf); - inboundMessages = inboundChannel.inboundMessages(); - Assert.assertTrue(inboundMessages.size() == 2); - } - - @Test - public void testDecodeResponse2() { - // 模拟 半个response数据包 - ByteBuf data1 = Unpooled.wrappedBuffer("response1".getBytes(StandardCharsets.UTF_8)); - DefaultFullHttpResponse response1 = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, data1); - response1.headers().add("Content-Length", data1.readableBytes()); - - EmbeddedChannel outboundChannel = new EmbeddedChannel(new HttpResponseEncoder()); - outboundChannel.writeOutbound(response1); - - CompositeByteBuf outboundByteBuf = Unpooled.compositeBuffer(); - for (Object msg : outboundChannel.outboundMessages()) { - outboundByteBuf.addComponent(true, (ByteBuf) msg); - } - - ByteBuf halfOutboundByteBuf = outboundByteBuf.slice(0, outboundByteBuf.readableBytes() / 2); - // -- 模拟完毕 - - EmbeddedChannel inboundChannel = new EmbeddedChannel(new HttpRequestResponseDecoder()); - - inboundChannel.writeInbound(halfOutboundByteBuf); - Queue inboundMessages = inboundChannel.inboundMessages(); - // 半个数据包读不出东西 - Assert.assertTrue(inboundMessages.size() == 0); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/User.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/User.java deleted file mode 100644 index ea7f84d0..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/User.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http; - -import java.util.List; -import java.util.Map; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class User { - - private Integer userId; - - private String name; - - private Map map; - - private List list; - - public Integer getUserId() { - return userId; - } - - public void setUserId(Integer userId) { - this.userId = userId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getMap() { - return map; - } - - public void setMap(Map map) { - this.map = map; - } - - public List getList() { - return list; - } - - public void setList(List list) { - this.list = list; - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStreamTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStreamTest.java deleted file mode 100644 index 9826254a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletInputStreamTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufInputStream; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.servlet.ReadListener; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; - -/** - * Created by liuruisen on 2020/6/30. - */ -public class ByteBufServletInputStreamTest { - - private ByteBufServletInputStream byteBufInputStream; - - private static final int LENGTH = "Test".getBytes().length; - private static final byte[] BYTES = "Test".getBytes(); - - @Before - public void setup() { - byteBufInputStream = new ByteBufServletInputStream(new ByteBufInputStream(Unpooled.wrappedBuffer(BYTES))); - } - - @Test - public void isFinished() throws IOException { - Assert.assertFalse(byteBufInputStream.isFinished()); - byte[] bytes1 = new byte[LENGTH]; - byteBufInputStream.read(bytes1); - Assert.assertTrue(byteBufInputStream.isFinished()); - } - - @Test - public void isReady() { - Assert.assertTrue(byteBufInputStream.isReady()); - } - - @Test(expected = UnsupportedOperationException.class) - public void setReadListener() { - byteBufInputStream.setReadListener(new ReadListener() { - @Override - public void onDataAvailable() throws IOException { - - } - - @Override - public void onAllDataRead() throws IOException { - - } - - @Override - public void onError(Throwable t) { - - } - }); - } - - @Test - public void read() throws IOException { - int byteValue = byteBufInputStream.read(); // read the next byte - - Assert.assertTrue((int) BYTES[0] == byteValue); - - Assert.assertEquals(byteBufInputStream.available(), LENGTH - 1); - } - - @Test - public void readBytes() throws IOException { - byte[] bytes1 = new byte[LENGTH]; - byteBufInputStream.read(bytes1); - Assert.assertEquals(new String(bytes1), "Test"); - Assert.assertEquals(byteBufInputStream.available(), 0); - } - - @Test - public void readBytesLen() throws IOException { - byte[] bytes1 = new byte[LENGTH]; - byteBufInputStream.read(bytes1, 0, 1); - Assert.assertEquals(bytes1[0], BYTES[0]); - } - - @Test - public void skip() throws IOException { - byteBufInputStream.skip(1); - Assert.assertEquals(byteBufInputStream.available(), LENGTH - 1); - } - - @Test - public void available() throws IOException { - Assert.assertEquals(byteBufInputStream.available(), LENGTH); - } - - @Test - public void close() throws IOException { - byteBufInputStream.close(); - // Assert.assertFalse(byteBufInputStream.isReady()); - } - - @Test - public void markSupported() { - Assert.assertTrue(byteBufInputStream.markSupported()); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStreamTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStreamTest.java deleted file mode 100644 index 82d48815..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/ByteBufServletOutputStreamTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufAllocator; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBufOutputStream; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.servlet.WriteListener; -import org.junit.Test; - -import java.io.IOException; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/10/19. - */ -public class ByteBufServletOutputStreamTest { - - @Test - public void isReady() throws IOException { - ByteBufServletOutputStream outputStream = - new ByteBufServletOutputStream(new ByteBufOutputStream(ByteBufAllocator.DEFAULT.buffer())); - - assertFalse(outputStream.isReady()); - - outputStream.write(1); - - assertTrue(outputStream.isReady()); - } - - @Test(expected = UnsupportedOperationException.class) - public void setWriteListener() { - ByteBufServletOutputStream outputStream = - new ByteBufServletOutputStream(new ByteBufOutputStream(Unpooled.wrappedBuffer("Test".getBytes()))); - outputStream.setWriteListener(new WriteListener() { - @Override - public void onWritePossible() throws IOException { - - } - - @Override - public void onError(Throwable throwable) { - - } - }); - } - - @Test - public void write() throws IOException { - ByteBufServletOutputStream outputStream = - new ByteBufServletOutputStream(new ByteBufOutputStream(ByteBufAllocator.DEFAULT.buffer())); - - assertFalse(outputStream.isReady()); - - outputStream.write(1); - - assertTrue(outputStream.getBufferSize() > 0); - } - - @Test - public void resetBuffer() throws IOException { - ByteBufServletOutputStream outputStream = - new ByteBufServletOutputStream(new ByteBufOutputStream(ByteBufAllocator.DEFAULT.buffer())); - assertFalse(outputStream.isReady()); - outputStream.write(1); - assertTrue(outputStream.isReady()); - outputStream.resetBuffer(); - assertFalse(outputStream.isReady()); - } - - @Test - public void getBufferSize() throws IOException { - ByteBufServletOutputStream outputStream = - new ByteBufServletOutputStream(new ByteBufOutputStream(ByteBufAllocator.DEFAULT.buffer())); - assertEquals(0, outputStream.getBufferSize()); - outputStream.write(1); - assertEquals(1, outputStream.getBufferSize()); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverterTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverterTest.java deleted file mode 100644 index 040530cd..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/BytesHttpMessageConverterTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/6/8. - */ -public class BytesHttpMessageConverterTest { - - private BytesHttpMessageConverter converter = new BytesHttpMessageConverter(); - - @Test - public void supports() { - assertTrue(converter.supports(this.getClass())); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolverTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolverTest.java deleted file mode 100644 index 54b8d8a0..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/EncodedRequestTemplateArgsResolverTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.querymap.FieldQueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.spring.SpringContract; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.protocol.http.User; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import org.junit.Assert; -import org.junit.Test; - -import java.util.List; - -import static com.baidu.cloud.starlight.api.exception.CodecException.PROTOCOL_ENCODE_EXCEPTION; - -/** - * Created by liuruisen on 2020/7/15. - */ -public class EncodedRequestTemplateArgsResolverTest { - - @Test - public void resolve() { - List metadats = new SpringContract().parseAndValidateMetadata(SpringRestService.class); - EncodedRequestTemplateArgsResolver resolver = new EncodedRequestTemplateArgsResolver(new FieldQueryMapEncoder(), - Target.EmptyTarget.create(SpringRestService.class), new JsonSerializer()); - - for (MethodMetadata metadata : metadats) { - if (metadata.method().getName().equalsIgnoreCase("post")) { - User user = new User(); - user.setName("Test"); - RequestTemplate template = resolver.create(new Object[] {user}, metadata); - Assert.assertTrue(template.body().length > 0); - break; - } - } - } - - @Test - public void resolveError() { - List metadats = new SpringContract().parseAndValidateMetadata(SpringRestService.class); - EncodedRequestTemplateArgsResolver resolver = new EncodedRequestTemplateArgsResolver(new FieldQueryMapEncoder(), - Target.EmptyTarget.create(SpringRestService.class), new JsonSerializer()); - - for (MethodMetadata metadata : metadats) { - if (metadata.method().getName().equalsIgnoreCase("post")) { - try { - RequestTemplate template = resolver.create(new Object[] {"Test"}, metadata); - } catch (Exception e) { - Assert.assertTrue(e instanceof CodecException); - Assert.assertTrue(((CodecException) e).getCode() == PROTOCOL_ENCODE_EXCEPTION); - } - break; - } - } - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptorTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptorTest.java deleted file mode 100644 index 57192e1a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletRequestAdaptorTest.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderValues; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.servlet.ServletException; -import com.baidu.cloud.thirdparty.servlet.ServletInputStream; -import com.baidu.cloud.thirdparty.servlet.http.Cookie; -import org.junit.Assert; -import org.junit.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/6/30. - */ -public class NettyServletRequestAdaptorTest { - - private static NettyServletRequestAdaptor adaptor; - - private static final int LENGTH = "TestTestTest".getBytes().length; - - private static final String PATH = "http://localhost:8080/spring-rest/post"; - - private static final String QUERTSTRING = "query=123"; - - static { - FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, - PATH + "?" + QUERTSTRING, Unpooled.wrappedBuffer("TestTestTest".getBytes())); - httpRequest.headers().add(HttpHeaderNames.COOKIE, "cookie1=cookie1;cookie2=cookie-cookie2"); - httpRequest.headers().add("HeaderKey", "TEST"); - httpRequest.headers().add("HeaderKeyInt", "123"); - httpRequest.headers().add(HttpHeaderNames.CONTENT_LENGTH, LENGTH); - httpRequest.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON); - - adaptor = new NettyServletRequestAdaptor(httpRequest); - } - - @Test - public void getAuthType() { - Assert.assertNull(adaptor.getAuthType()); - } - - @Test - public void getCookies() { - Cookie[] cookies = adaptor.getCookies(); - Assert.assertEquals(cookies.length, 2); - Assert.assertEquals(cookies[0].getName(), "cookie1"); - Assert.assertEquals(cookies[0].getValue(), "cookie1"); - } - - @Test - public void getDateHeader() { - Assert.assertEquals(adaptor.getDateHeader("DataHeader"), 0); - } - - @Test - public void getHeader() { - Assert.assertEquals(adaptor.getHeader("HeaderKey"), "TEST"); - } - - @Test - public void getHeaders() { - Enumeration values = adaptor.getHeaders("HeaderKey"); - Assert.assertEquals(values.nextElement(), "TEST"); - } - - @Test - public void getHeaderNames() { - Enumeration names = adaptor.getHeaderNames(); - List nameList = new ArrayList<>(); - while (names.hasMoreElements()) { - nameList.add(names.nextElement()); - } - assertTrue(nameList.size() > 0); - assertTrue(nameList.toString().contains("HeaderKey")); - } - - @Test - public void getIntHeader() { - int value = adaptor.getIntHeader("HeaderKeyInt"); - Assert.assertEquals(value, 123); - } - - @Test - public void getMethod() { - Assert.assertEquals(adaptor.getMethod(), HttpMethod.POST.name()); - } - - @Test - public void getPathInfo() { - Assert.assertNull(adaptor.getPathInfo()); - } - - @Test - public void getPathTranslated() { - Assert.assertNull(adaptor.getPathTranslated()); - } - - @Test - public void getContextPath() { - Assert.assertEquals(adaptor.getContextPath(), PATH); - } - - @Test - public void getQueryString() { - Assert.assertEquals(adaptor.getQueryString(), QUERTSTRING); - } - - @Test - public void getRemoteUser() { - Assert.assertNull(adaptor.getRemoteUser()); - } - - @Test - public void isUserInRole() { - Assert.assertFalse(adaptor.isUserInRole("null")); - } - - @Test - public void getUserPrincipal() { - Assert.assertNull(adaptor.getUserPrincipal()); - } - - @Test - public void getRequestedSessionId() { - Assert.assertNull(adaptor.getRequestedSessionId()); - } - - @Test - public void getRequestURI() { - Assert.assertEquals(adaptor.getRequestURI(), PATH); - } - - @Test - public void getRequestURL() { - try { - adaptor.getRequestURL(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getServletPath() { - Assert.assertEquals(adaptor.getServletPath(), PATH); - - } - - @Test - public void getSession() { - Assert.assertNull(adaptor.getSession()); - - } - - @Test - public void testGetSession() { - Assert.assertNull(adaptor.getSession(true)); - } - - @Test - public void changeSessionId() { - Assert.assertNull(adaptor.changeSessionId()); - } - - @Test - public void isRequestedSessionIdValid() { - Assert.assertFalse(adaptor.isRequestedSessionIdValid()); - } - - @Test - public void isRequestedSessionIdFromCookie() { - Assert.assertFalse(adaptor.isRequestedSessionIdFromCookie()); - } - - @Test - public void isRequestedSessionIdFromURL() { - Assert.assertFalse(adaptor.isRequestedSessionIdFromURL()); - } - - @Test - public void isRequestedSessionIdFromURLNew() { - Assert.assertFalse(adaptor.isRequestedSessionIdFromUrl()); - } - - @Test - public void authenticate() throws IOException, ServletException { - Assert.assertFalse(adaptor.authenticate(null)); - } - - @Test - public void login() { - try { - adaptor.login("user", "passw"); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void logout() { - try { - adaptor.logout(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getParts() { - try { - adaptor.getParts(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getPart() { - try { - adaptor.getPart("name"); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void upgrade() { - try { - adaptor.upgrade(null); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getAttribute() { - Assert.assertNull(adaptor.getAttribute("attr1")); - adaptor.setAttribute("attr1", "att1"); - adaptor.setAttribute("attr2", "att2"); - - Assert.assertEquals(adaptor.getAttribute("attr1"), "att1"); - - Enumeration names = adaptor.getAttributeNames(); - List nameList = new ArrayList<>(); - while (names.hasMoreElements()) { - nameList.add(names.nextElement()); - } - assertTrue(nameList.size() > 0); - assertTrue(nameList.toString().contains("attr1")); - assertTrue(nameList.toString().contains("attr2")); - - adaptor.removeAttribute("attr2"); - Assert.assertNull(adaptor.getAttribute("attr2")); - } - - @Test - public void getCharacterEncoding() { - Assert.assertEquals(adaptor.getCharacterEncoding(), "UTF-8"); - } - - @Test - public void setCharacterEncoding() { - try { - adaptor.setCharacterEncoding(null); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getContentLength() { - Assert.assertEquals(adaptor.getContentLength(), LENGTH); - } - - @Test - public void getContentLengthLong() { - Assert.assertEquals(adaptor.getContentLength(), LENGTH); - } - - @Test - public void getContentType() { - Assert.assertEquals(adaptor.getContentType(), HttpHeaderValues.APPLICATION_JSON.toString()); - } - - @Test - public void getInputStream() throws IOException { - ServletInputStream servletInputStream = adaptor.getInputStream(); - assertTrue(servletInputStream instanceof ByteBufServletInputStream); - assertTrue((servletInputStream).isReady()); - } - - @Test - public void getParameter() { - Assert.assertEquals(adaptor.getParameter("query"), "123"); - } - - @Test - public void getParameterNames() { - Enumeration names = adaptor.getParameterNames(); - List nameList = new ArrayList<>(); - while (names.hasMoreElements()) { - nameList.add(names.nextElement()); - } - assertTrue(nameList.size() > 0); - assertTrue(nameList.toString().contains("query")); - } - - @Test - public void getParameterValues() { - String[] values = adaptor.getParameterValues("query"); - Assert.assertEquals(values.length, 1); - Assert.assertEquals(values[0], "123"); - } - - @Test - public void getParameterMap() { - Map parameterMap = adaptor.getParameterMap(); - Assert.assertEquals(parameterMap.get("query")[0], "123"); - } - - @Test - public void getProtocol() { - Assert.assertEquals(adaptor.getProtocol(), HttpVersion.HTTP_1_1.protocolName()); - } - - @Test - public void getScheme() { - Assert.assertEquals(adaptor.getScheme(), HttpVersion.HTTP_1_1.protocolName().toLowerCase()); - } - - @Test - public void getServerName() { - try { - adaptor.getServerName(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getServerPort() { - try { - adaptor.getServerPort(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getReader() { - try { - adaptor.getReader(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getRemoteAddr() { - try { - adaptor.getRemoteAddr(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getRemoteHost() { - try { - adaptor.getRemoteHost(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getLocale() { - try { - adaptor.getLocale(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getLocales() { - try { - adaptor.getLocales(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void isSecure() { - Assert.assertFalse(adaptor.isSecure()); - } - - @Test - public void getRequestDispatcher() { - try { - adaptor.getRequestDispatcher("/spring-rest"); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getRealPath() { - try { - adaptor.getRealPath("/spring-rest"); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getRemotePort() { - try { - adaptor.getRemotePort(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getLocalName() { - try { - adaptor.getLocalName(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getLocalAddr() { - try { - adaptor.getLocalAddr(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getLocalPort() { - try { - adaptor.getLocalPort(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void getServletContext() { - Assert.assertNull(adaptor.getServletContext()); - } - - @Test - public void startAsync() { - try { - adaptor.startAsync(); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void testStartAsync() { - try { - adaptor.startAsync(null, null); - } catch (Exception e) { - assertTrue(e instanceof UnsupportedOperationException); - } - } - - @Test - public void isAsyncStarted() { - Assert.assertFalse(adaptor.isAsyncStarted()); - } - - @Test - public void isAsyncSupported() { - Assert.assertFalse(adaptor.isAsyncSupported()); - } - - @Test - public void getAsyncContext() { - Assert.assertNull(adaptor.getAsyncContext()); - } - - @Test - public void getDispatcherType() { - Assert.assertNull(adaptor.getDispatcherType()); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptorTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptorTest.java deleted file mode 100644 index 5428674b..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/NettyServletResponseAdaptorTest.java +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.servlet.ServletOutputStream; -import com.baidu.cloud.thirdparty.servlet.http.Cookie; -import org.junit.Test; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Date; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/10/19. - */ -public class NettyServletResponseAdaptorTest { - - @Test - public void addCookie() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.SET_COOKIE.toString())); - - Cookie cookie = new Cookie("name", "test user"); - cookie.setComment("comment"); - cookie.setDomain("www.baidu.com"); - cookie.setHttpOnly(true); - cookie.setMaxAge(150); - cookie.setPath("/test"); - cookie.setSecure(false); - cookie.setVersion(1); - - responseAdaptor.addCookie(cookie); - - assertNotNull(responseAdaptor.getHeader(HttpHeaderNames.SET_COOKIE.toString())); - } - - @Test - public void containsHeader() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertFalse(responseAdaptor.containsHeader("test")); - - responseAdaptor.addHeader("test", "value"); - - assertTrue(responseAdaptor.containsHeader("test")); - - assertEquals("value", responseAdaptor.getHeader("test")); - } - - @Test - public void encodeURL() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - String url = responseAdaptor.encodeURL("http://www.baidu.com/query=123"); - assertNotEquals("http://www.baidu.com/query=123", url); - } - - @Test - public void encodeRedirectURL() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - String url = responseAdaptor.encodeRedirectURL("http://www.baidu.com/query=123"); - assertNotEquals("http://www.baidu.com/query=123", url); - } - - @Test - public void encodeLowercaseUrl() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - String url = responseAdaptor.encodeUrl("http://www.baidu.com/query=123"); - assertNotEquals("http://www.baidu.com/query=123", url); - } - - @Test - public void encodeLowercaseRedirectUrl() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - String url = responseAdaptor.encodeRedirectUrl("http://www.baidu.com/query=123"); - assertNotEquals("http://www.baidu.com/query=123", url); - } - - @Test - public void sendError() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(200, responseAdaptor.getStatus()); - - responseAdaptor.sendError(500); - - assertEquals(500, responseAdaptor.getStatus()); - } - - @Test - public void testSendError() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(200, responseAdaptor.getStatus()); - - responseAdaptor.sendError(500, "error"); - - assertEquals(500, responseAdaptor.getStatus()); - - } - - @Test - public void sendRedirect() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.LOCATION.toString())); - - responseAdaptor.sendRedirect("www.baidu.com"); - - assertEquals("www.baidu.com", responseAdaptor.getHeader(HttpHeaderNames.LOCATION.toString())); - } - - @Test - public void setDateHeader() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.DATE.toString())); - - Date oriDate = new Date(); - responseAdaptor.addDateHeader(HttpHeaderNames.DATE.toString(), oriDate.getTime()); - - assertNotNull(responseAdaptor.getHeader(HttpHeaderNames.DATE.toString())); - - Date date = new Date(); - responseAdaptor.setDateHeader(HttpHeaderNames.DATE.toString(), date.getTime()); - - assertNotEquals(oriDate.getTime(), responseAdaptor.getHeader(HttpHeaderNames.DATE.toString())); - } - - @Test - public void addDateHeader() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.DATE.toString())); - - Date oriDate = new Date(); - responseAdaptor.addDateHeader(HttpHeaderNames.DATE.toString(), oriDate.getTime()); - - assertNotNull(responseAdaptor.getHeader(HttpHeaderNames.DATE.toString())); - } - - @Test - public void setHeader() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader("Test")); - - responseAdaptor.addHeader("Test", "v1"); - - assertNotNull(responseAdaptor.getHeader("Test")); - - responseAdaptor.setHeader("Test", "v2"); - - assertEquals("v2", responseAdaptor.getHeader("Test")); - } - - @Test - public void setIntHeader() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader("Test")); - - responseAdaptor.addIntHeader("Test", 1); - - assertNotNull(responseAdaptor.getHeader("Test")); - - responseAdaptor.setIntHeader("Test", 2); - - assertEquals(String.valueOf(2), responseAdaptor.getHeader("Test")); - } - - @Test - public void setStatus() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(200, responseAdaptor.getStatus()); - - responseAdaptor.setStatus(600); - - assertEquals(600, responseAdaptor.getStatus()); - } - - @Test - public void testSetStatus() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(200, responseAdaptor.getStatus()); - - responseAdaptor.setStatus(600, "Error 600"); - - assertEquals(600, responseAdaptor.getStatus()); - } - - @Test - public void getStatus() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(200, responseAdaptor.getStatus()); - } - - @Test - public void getHeaders() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader("Test")); - - responseAdaptor.setHeader("Test", "v1"); - assertNotNull(responseAdaptor.getHeader("Test")); - - assertEquals(1, responseAdaptor.getHeaders("Test").size()); - } - - @Test - public void getHeaderNames() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(0, responseAdaptor.getHeaderNames().size()); - responseAdaptor.setHeader("Test", "v1"); - - assertEquals(1, responseAdaptor.getHeaderNames().size()); - } - - @Test - public void getCharacterEncoding() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals("utf-8", responseAdaptor.getCharacterEncoding()); - } - - @Test - public void getContentType() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getContentType()); - - responseAdaptor.setContentType("application/json"); - - assertNotNull(responseAdaptor.getContentType()); - - assertEquals("application/json", responseAdaptor.getContentType()); - - } - - @Test - public void getOutputStream() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNotNull(responseAdaptor.getOutputStream()); - - ServletOutputStream outputStream = responseAdaptor.getOutputStream(); - - assertFalse(outputStream.isReady()); - - outputStream.write(1); - - assertTrue(outputStream.isReady()); - } - - @Test - public void getWriter() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNotNull(responseAdaptor.getWriter()); - } - - @Test - public void setCharacterEncoding() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals("utf-8", responseAdaptor.getCharacterEncoding()); - - responseAdaptor.setCharacterEncoding("GBK"); - - assertEquals("GBK", responseAdaptor.getCharacterEncoding()); - } - - @Test - public void setContentLength() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.CONTENT_LENGTH.toString())); - - responseAdaptor.setContentLength(6666); - - assertEquals(Integer.valueOf(6666), - Integer.valueOf(responseAdaptor.getHeader(HttpHeaderNames.CONTENT_LENGTH.toString()))); - - } - - @Test - public void setContentLengthLong() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.CONTENT_LENGTH.toString())); - - responseAdaptor.setContentLengthLong(6666L); - - assertEquals(Integer.valueOf(6666), - Integer.valueOf(responseAdaptor.getHeader(HttpHeaderNames.CONTENT_LENGTH.toString()))); - } - - @Test - public void setContentType() { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertNull(responseAdaptor.getHeader(HttpHeaderNames.CONTENT_TYPE.toString())); - - responseAdaptor.setContentType("text/html"); - - assertEquals("text/html", responseAdaptor.getContentType()); - } - - @Test - public void setBufferSize() {} - - @Test - public void getBufferSize() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertEquals(0l, responseAdaptor.getBufferSize()); - } - - @Test - public void flushBuffer() throws IOException { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - assertFalse(responseAdaptor.isCommitted()); - - responseAdaptor.flushBuffer(); - - assertTrue(responseAdaptor.isCommitted()); - } - - @Test - public void resetBuffer() throws IOException { - - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - responseAdaptor.getWriter().write(1); - responseAdaptor.getWriter().flush(); - - assertEquals(1, responseAdaptor.getBufferSize()); - - responseAdaptor.resetBuffer(); - - assertEquals(0, responseAdaptor.getBufferSize()); - } - - @Test - public void reset() { - FullHttpResponse nettyResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - NettyServletResponseAdaptor responseAdaptor = new NettyServletResponseAdaptor(nettyResponse); - - responseAdaptor.addHeader("Test", "Value"); - responseAdaptor.reset(); - assertNull(responseAdaptor.getHeader("Test")); - - try { - responseAdaptor.reset(); - } catch (Exception e) { - assertTrue(e instanceof IllegalStateException); - } - - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolverTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolverTest.java deleted file mode 100644 index de5c439e..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateArgsResolverTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.feign.MethodMetadata; -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import com.baidu.cloud.thirdparty.feign.Target; -import com.baidu.cloud.thirdparty.feign.querymap.FieldQueryMapEncoder; -import com.baidu.cloud.thirdparty.feign.spring.SpringContract; -import org.junit.Assert; -import org.junit.Test; - -import java.util.List; - -/** - * Created by liuruisen on 2020/7/15. - */ -public class RequestTemplateArgsResolverTest { - - @Test - public void create() { - - List metadats = new SpringContract().parseAndValidateMetadata(SpringRestService.class); - RequestTemplateArgsResolver resolver = new RequestTemplateArgsResolver(new FieldQueryMapEncoder(), - Target.EmptyTarget.create(SpringRestService.class)); - - for (MethodMetadata metadata : metadats) { - switch (metadata.method().getName().toLowerCase()) { - case "get": - RequestTemplate template = resolver.create(new Object[] {"Test", "Test"}, metadata); - Assert.assertTrue(template.queries().size() == 1); - Assert.assertTrue(template.queries().get("query").contains("Test")); - break; - case "delete": - RequestTemplate template1 = resolver.create(new Object[] {"Test"}, metadata); - Assert.assertTrue(template1.path().contains("Test")); - break; - case "getquerymap": - RequestTemplate template2 = resolver.create(new Object[] {"Test1", "Test2"}, metadata); - Assert.assertTrue(template2.queries().size() == 2); - Assert.assertTrue(template2.queries().get("query1").contains("Test1")); - Assert.assertTrue(template2.queries().get("query2").contains("Test2")); - break; - } - } - - } - -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGeneratorTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGeneratorTest.java deleted file mode 100644 index f4f856d1..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RequestTemplateGeneratorTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.feign.RequestTemplate; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * Created by liuruisen on 2020/7/15. - */ -public class RequestTemplateGeneratorTest { - - @Test - public void create() { - RequestTemplateArgsResolver resolver = Mockito.mock(RequestTemplateArgsResolver.class); - RequestTemplate template = new RequestTemplate(); - when(resolver.create(any(), any())).thenReturn(template); - - RequestTemplateGenerator generator = new RequestTemplateGenerator(null, resolver); - RequestTemplate requestTemplate = generator.create(new Object[] {"Test"}); - Assert.assertTrue(requestTemplate == template); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RestService.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RestService.java deleted file mode 100644 index 5d4688df..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/RestService.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.DeleteMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.ModelAttribute; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PathVariable; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PutMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestParam; -import com.baidu.cloud.starlight.protocol.http.User; - -/** - * Created by liuruisen on 2020/7/28. - */ -@RequestMapping("/rest") -public interface RestService { - - @GetMapping("/{id}") - String get(@PathVariable("id") String id, @RequestParam("query") String query); - - @PutMapping - String put(@RequestBody User user); - - @DeleteMapping("{id}") - String delete(@PathVariable("id") String id); - - @PostMapping - String post(@ModelAttribute User user); - - @GetMapping - // not support querymap - String getQueryMap(@RequestParam("query1") String query1, @RequestParam("query2") String query2); -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMappingTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMappingTest.java deleted file mode 100644 index 777de661..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHandlerMappingTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.starlight.protocol.http.User; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/6/30. - */ -public class SpringRestHandlerMappingTest { - - @Test - public void getInstance() { - SpringRestHandlerMapping handlerMapping1 = SpringRestHandlerMapping.getInstance(); - SpringRestHandlerMapping handlerMapping2 = SpringRestHandlerMapping.getInstance(); - Assert.assertTrue(handlerMapping1 == handlerMapping2); - } - - @Test - public void createMapping() { - SpringRestHandlerMapping handlerMapping = SpringRestHandlerMapping.getInstance(); - handlerMapping.createMapping(RestService.class, new RestService() { - @Override - public String get(String id, String query) { - return null; - } - - @Override - public String put(User user) { - return null; - } - - @Override - public String delete(String id) { - return null; - } - - @Override - public String post(User user) { - return null; - } - - @Override - public String getQueryMap(String query1, String query2) { - return null; - } - }); - - handlerMapping.createMapping(null, null); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoderTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoderTest.java deleted file mode 100644 index cfe55914..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpDecoderTest.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpMethod; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; -import com.baidu.cloud.starlight.protocol.http.User; -import com.baidu.cloud.starlight.serialization.serializer.JsonSerializer; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.Collections; - -/** - * Created by liuruisen on 2020/6/30. - */ -public class SpringRestHttpDecoderTest { - - private static final SpringRestHttpDecoder springDecoder = new SpringRestHttpDecoder(); - - private static FullHttpRequest getRequest; - - private static FullHttpRequest putRequest; - - private static FullHttpRequest deletRequest; - - private static FullHttpRequest postRequest; - - private static FullHttpRequest illegalHttpRequest; - - private static FullHttpRequest queryMapRequest; - - static { - SpringRestHttpEncoder httpEncoder = new SpringRestHttpEncoder(); - RpcRequest rpcRequest = new RpcRequest(1); - rpcRequest.setServiceClass(SpringRestService.class); - rpcRequest.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - - // get http request - try { - rpcRequest.setMethod(SpringRestService.class.getMethod("get", String.class, String.class)); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - rpcRequest.setMethodName("get"); - rpcRequest.setParams(new Object[] {"1", "123"}); - rpcRequest.setParamsTypes(new Class[] {String.class, String.class}); - - getRequest = httpEncoder.convertRequest(rpcRequest); - - illegalHttpRequest = httpEncoder.convertRequest(rpcRequest); - illegalHttpRequest.setMethod(HttpMethod.POST); - - try { - rpcRequest.setMethod(SpringRestService.class.getMethod("getQueryMap", String.class, String.class)); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - rpcRequest.setMethodName("getQueryMap"); - rpcRequest.setParams(new Object[] {"123", "456"}); - rpcRequest.setParamsTypes(new Class[] {String.class, String.class}); - queryMapRequest = httpEncoder.convertRequest(rpcRequest); - - User user = new User(); - user.setUserId(12); - user.setName("test"); - // put http request - rpcRequest.setMethodName("put"); - try { - rpcRequest.setMethod(SpringRestService.class.getMethod("put", User.class)); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - rpcRequest.setParams(new Object[] {user}); - rpcRequest.setParamsTypes(new Class[] {User.class}); - - putRequest = httpEncoder.convertRequest(rpcRequest); - - // delete http request - rpcRequest.setMethodName("delete"); - try { - rpcRequest.setMethod(SpringRestService.class.getMethod("delete", String.class)); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - rpcRequest.setParams(new Object[] {"1"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - - deletRequest = httpEncoder.convertRequest(rpcRequest); - - // post http request - rpcRequest.setMethodName("post"); - try { - rpcRequest.setMethod(SpringRestService.class.getMethod("post", User.class)); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - rpcRequest.setParams(new Object[] {user}); - rpcRequest.setParamsTypes(new Class[] {User.class}); - rpcRequest.setAttachmentKv(Collections.singletonMap("headerKey", "headerValue")); - - postRequest = httpEncoder.convertRequest(rpcRequest); - - SpringRestHandlerMapping handlerMapping = SpringRestHandlerMapping.getInstance(); - handlerMapping.createMapping(SpringRestService.class, new SpringRestService() { - @Override - public String get(String id, String query) { - return null; - } - - @Override - public String put(User user) { - return null; - } - - @Override - public String delete(String id) { - return null; - } - - @Override - public String post(User user) { - return null; - } - - @Override - public String getQueryMap(String query1, String query2) { - return null; - } - }); - } - - @Ignore - @Test - public void reverseConvertGetRequest() { - - RpcRequest getRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(getRequest); - Assert.assertNotNull(getRpcRequest); - Assert.assertEquals(getRpcRequest.getMethodName(), "get"); - Assert.assertEquals(getRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(getRpcRequest); - Assert.assertEquals(getRpcRequest.getParams().length, 2); - Assert.assertEquals(getRpcRequest.getParams()[0], "1"); - } - - @Ignore - @Test - public void reverseConvertPostRequest() { - - // decode post request - RpcRequest postRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(postRequest); - Assert.assertNotNull(postRpcRequest); - Assert.assertEquals(postRpcRequest.getMethodName(), "post"); - Assert.assertEquals(postRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(postRpcRequest); - Assert.assertEquals(postRpcRequest.getParams().length, 1); - springDecoder.decodeBody(postRpcRequest); - Assert.assertNotNull(postRpcRequest.getParams()[0]); - - } - - @Test - public void reverseConvertRequest() { - JsonSerializer serializer = new JsonSerializer(); - - // decode get request - RpcRequest getRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(getRequest); - Assert.assertNotNull(getRpcRequest); - Assert.assertEquals(getRpcRequest.getMethodName(), "get"); - Assert.assertEquals(getRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(getRpcRequest); - Assert.assertEquals(getRpcRequest.getParams().length, 2); - Assert.assertEquals(getRpcRequest.getParams()[0], "1"); - - // decode get query map request - RpcRequest queryMapRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(queryMapRequest); - Assert.assertNotNull(queryMapRpcRequest); - Assert.assertEquals(queryMapRpcRequest.getMethodName(), "getQueryMap"); - Assert.assertEquals(queryMapRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(queryMapRpcRequest); - Assert.assertEquals(queryMapRpcRequest.getParams().length, 2); - Assert.assertEquals(queryMapRpcRequest.getParams()[0], "123"); - Assert.assertEquals(queryMapRpcRequest.getParams()[1], "456"); - - // decode post request - RpcRequest postRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(postRequest); - Assert.assertNotNull(postRpcRequest); - Assert.assertEquals(postRpcRequest.getMethodName(), "post"); - Assert.assertEquals(postRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(postRpcRequest); - Assert.assertEquals(postRpcRequest.getParams().length, 1); - // Assert.assertTrue(postRpcRequest.getParams()[0] instanceof byte[]); - User postUser = (User) postRpcRequest.getParams()[0]; - // Assert.assertEquals(postUser.getName(), "test"); - - // decode put request - RpcRequest putRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(putRequest); - Assert.assertNotNull(putRpcRequest); - Assert.assertEquals(putRpcRequest.getMethodName(), "put"); - Assert.assertEquals(putRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(putRpcRequest); - Assert.assertEquals(putRpcRequest.getParams().length, 1); - // Assert.assertTrue(postRpcRequest.getParams()[0] instanceof byte[]); - // User putUser = (User) serializer.deserialize((byte[]) postRpcRequest.getParams()[0], User.class); - // Assert.assertEquals(putUser.getName(), "test"); - - // decode delete request - RpcRequest deleteRpcRequest = (RpcRequest) springDecoder.reverseConvertRequest(deletRequest); - Assert.assertNotNull(deleteRpcRequest); - Assert.assertEquals(deleteRpcRequest.getMethodName(), "delete"); - Assert.assertEquals(deleteRpcRequest.getServiceName(), SpringRestService.class.getName()); - Assert.assertNotNull(deleteRpcRequest); - Assert.assertEquals(deleteRpcRequest.getParams().length, 1); - Assert.assertEquals(deleteRpcRequest.getParams()[0], "1"); - } - - @Test(expected = Exception.class) - public void reverseConvertRequestError() { - // reverseConvertResponseError - springDecoder.reverseConvertRequest(illegalHttpRequest); - - illegalHttpRequest.setUri("/spring/1"); - springDecoder.reverseConvertRequest(illegalHttpRequest); - } - - @Test - public void reverseConvertResponse() { - FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - httpResponse.headers().set(AbstractHttpProtocol.X_STARLIGHT_ID, 1l); - Response response = springDecoder.reverseConvertResponse(httpResponse); - Assert.assertEquals(response.getProtocolName(), SpringRestProtocol.PROTOCOL_NAME); - } - -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoderTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoderTest.java deleted file mode 100644 index 9986ac61..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestHttpEncoderTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.netty.handler.codec.http.FullHttpRequest; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.protocol.http.User; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Collections; - -/** - * Created by liuruisen on 2020/6/30. - */ -public class SpringRestHttpEncoderTest { - - private static final SpringRestHttpEncoder httpEncoder = new SpringRestHttpEncoder(); - - @Test - public void convertPostRequest() throws NoSuchMethodException { - User user = new User(); - user.setUserId(12); - user.setName("test"); - RpcRequest rpcRequest = new RpcRequest(1); - rpcRequest.setServiceClass(SpringRestService.class); - rpcRequest.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - // post http request - rpcRequest.setMethodName("post"); - rpcRequest.setMethod(SpringRestService.class.getMethod("post", User.class)); - rpcRequest.setParams(new Object[] {user}); - rpcRequest.setParamsTypes(new Class[] {User.class}); - rpcRequest.setAttachmentKv(Collections.singletonMap("headerKey", "headerValue")); - - FullHttpRequest postRequest = httpEncoder.convertRequest(rpcRequest); - Assert.assertNotNull(postRequest); - Assert.assertNotNull(postRequest.uri()); - Assert.assertTrue(postRequest.uri().contains("/spring-rest")); - Assert.assertTrue(postRequest.method().name().equalsIgnoreCase("post")); - Assert.assertNotNull(postRequest.content()); - Assert.assertEquals(postRequest.headers().get("headerKey"), "headerValue"); - } - - @Test - public void convertRequest() throws NoSuchMethodException { - RpcRequest rpcRequest = new RpcRequest(1); - rpcRequest.setServiceClass(SpringRestService.class); - rpcRequest.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - - // get http request - rpcRequest.setMethod(SpringRestService.class.getMethod("get", String.class, String.class)); - rpcRequest.setMethodName("get"); - rpcRequest.setParams(new Object[] {"1", "123"}); - rpcRequest.setParamsTypes(new Class[] {String.class, String.class}); - - FullHttpRequest getRequest = httpEncoder.convertRequest(rpcRequest); - Assert.assertNotNull(getRequest); - Assert.assertNotNull(getRequest.uri()); - Assert.assertTrue(getRequest.uri().contains("/spring-rest/1")); - Assert.assertTrue(getRequest.method().name().equalsIgnoreCase("get")); - - User user = new User(); - user.setUserId(12); - user.setName("test"); - // put http request - rpcRequest.setMethodName("put"); - rpcRequest.setMethod(SpringRestService.class.getMethod("put", User.class)); - rpcRequest.setParams(new Object[] {user}); - rpcRequest.setParamsTypes(new Class[] {User.class}); - - FullHttpRequest putRequest = httpEncoder.convertRequest(rpcRequest); - Assert.assertNotNull(putRequest); - Assert.assertNotNull(putRequest.uri()); - Assert.assertTrue(putRequest.uri().contains("/spring-rest")); - Assert.assertTrue(putRequest.method().name().equalsIgnoreCase("put")); - Assert.assertNotNull(putRequest.content()); - - // delete http request - rpcRequest.setMethodName("delete"); - rpcRequest.setMethod(SpringRestService.class.getMethod("delete", String.class)); - rpcRequest.setParams(new Object[] {"1"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - - FullHttpRequest deletRequest = httpEncoder.convertRequest(rpcRequest); - Assert.assertNotNull(deletRequest); - Assert.assertNotNull(deletRequest.uri()); - Assert.assertTrue(deletRequest.uri().contains("/spring-rest")); - Assert.assertTrue(deletRequest.method().name().equalsIgnoreCase("delete")); - - // post http request - rpcRequest.setMethodName("post"); - rpcRequest.setMethod(SpringRestService.class.getMethod("post", User.class)); - rpcRequest.setParams(new Object[] {user}); - rpcRequest.setParamsTypes(new Class[] {User.class}); - rpcRequest.setAttachmentKv(Collections.singletonMap("headerKey", "headerValue")); - - FullHttpRequest postRequest = httpEncoder.convertRequest(rpcRequest); - Assert.assertNotNull(postRequest); - Assert.assertNotNull(postRequest.uri()); - Assert.assertTrue(postRequest.uri().contains("/spring-rest")); - Assert.assertTrue(postRequest.method().name().equalsIgnoreCase("post")); - Assert.assertNotNull(postRequest.content()); - Assert.assertEquals(postRequest.headers().get("headerKey"), "headerValue"); - } - - @Test - public void convertRequestError() throws NoSuchMethodException { - RpcRequest rpcRequest = new RpcRequest(1); - rpcRequest.setServiceClass(SpringRestService.class); - rpcRequest.setProtocolName(SpringRestProtocol.PROTOCOL_NAME); - - // error method - rpcRequest.setMethod(this.getClass().getMethod("convertRequestError")); - try { - httpEncoder.convertRequest(rpcRequest); - } catch (Exception e) { - Assert.assertTrue(e instanceof CodecException); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocolTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocolTest.java deleted file mode 100644 index 6aa6db0a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestProtocolTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class SpringRestProtocolTest { - - private SpringRestProtocol springRestProtocol = new SpringRestProtocol(); - - @Test - public void getEncoder() { - Assert.assertTrue(springRestProtocol.getEncoder() != null); - Assert.assertTrue(springRestProtocol.getEncoder() instanceof SpringRestHttpEncoder); - } - - @Test - public void getDecoder() { - Assert.assertTrue(springRestProtocol.getDecoder() != null); - Assert.assertTrue(springRestProtocol.getDecoder() instanceof SpringRestHttpDecoder); - } - -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestService.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestService.java deleted file mode 100644 index ecae5c5a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/SpringRestService.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest; - -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.DeleteMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.GetMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.ModelAttribute; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PathVariable; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PostMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.PutMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestBody; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestMapping; -import com.baidu.cloud.thirdparty.springframework.web.bind.annotation.RequestParam; -import com.baidu.cloud.starlight.protocol.http.User; - -/** - * Created by liuruisen on 2020/6/30. - */ -@RequestMapping("/spring-rest") -public interface SpringRestService { - - @GetMapping("/{id}") - String get(@PathVariable("id") String id, @RequestParam("query") String query); - - @PutMapping - String put(@RequestBody User user); - - @DeleteMapping("{id}") - String delete(@PathVariable("id") String id); - - @PostMapping - String post(@ModelAttribute User user); - - @GetMapping - // not support querymap - String getQueryMap(@RequestParam("query1") String query1, @RequestParam("query2") String query2); -} diff --git a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocolTest.java b/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocolTest.java deleted file mode 100644 index d668930d..00000000 --- a/starlight/starlight-protocol/starlight-protocol-http/src/test/java/com/baidu/cloud/starlight/protocol/http/springrest/sse/SpringRestSseProtocolTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.http.springrest.sse; - -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.protocol.http.AbstractHttpProtocol; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultLastHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObject; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.LastHttpContent; -import org.junit.Assert; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static com.baidu.cloud.starlight.api.common.Constants.PROTOCOL_KEY; -import static com.baidu.cloud.starlight.api.common.Constants.SSE_EMBEDDED_CHANNEL_KEY; -import static com.baidu.cloud.starlight.api.common.Constants.SSE_REQUEST_ID_KEY; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SpringRestSseProtocolTest { - - @Test - public void test1() { - EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpResponseEncoder()); - // part1 - HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/event-stream;charset=UTF-8"); - httpResponse.headers().set(HttpHeaderNames.CACHE_CONTROL, "no-cache"); - httpResponse.headers().set(HttpHeaderNames.CONNECTION, "keep-alive"); - httpResponse.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "chunked"); - // request-id - httpResponse.headers().set(AbstractHttpProtocol.X_STARLIGHT_ID, 1); - // 适配零信任网关SSE逻辑,参考文档:https://ku.baidu-int.com/knowledge/HFVrC7hq1Q/b_dB7xLNHi/yToZib1hj4/hZlgASbuCxSw11 - httpResponse.headers().set("X-Accel-Buffering", "no"); - - // part2 - String data = - "data:{\"status\":200,\"data\":{\"sessionId\":\"AIX-618e2f8e-8e96-4076-911c-9054ee476b2a\",\"answer\":{\"content\":\"为您找到全部营销方案。\",\"cards\":[],\"instructions\":[{\"type\":202,\"payload\":{\"campaignParams\":{\"orderby\":\"addTime\",\"rowFilters\":[],\"limit\":[500],\"desc\":true},\"reportParams\":{\"token\":\"409f4eaa-ad19-464f-ac33-ab8b480asdds\",\"reportType\":1900001,\"userIds\":[630152],\"startDate\":\"2024-05-14\",\"endDate\":\"2024-05-14\",\"timeUnit\":\"SUMMARY\",\"columns\":[\"userId\",\"campaignNameStatus\",\"campaignId\",\"click\",\"ocpcTargetTrans\",\"deepConversions\",\"cost\",\"impression\",\"aixOcpcConversionsDetail28CVR\",\"aixOcpcConversionsDetail29CVR\"],\"startRow\":0,\"rowCount\":200,\"needSum\":true,\"needCache\":false,\"addZeroRows\":false,\"withColumnMeta\":false,\"topCount\":0},\"distribution\":\"space-between\",\"instructionParameters\":{\"reportParams\":{\"token\":\"409f4eaa-ad19-464f-ac33-ab8b480asdds\",\"reportType\":1900040,\"userIds\":[630152],\"startDate\":\"2024-05-14\",\"endDate\":\"2024-05-14\",\"timeUnit\":\"SUMMARY\",\"columns\":[\"userId\",\"projectNameStatus\",\"projectId\",\"click\",\"ocpcTargetTrans\",\"deepConversions\",\"cost\",\"impression\",\"aixOcpcConversionsDetail28CVR\",\"aixOcpcConversionsDetail29CVR\"],\"startRow\":0,\"rowCount\":200,\"needSum\":true,\"needCache\":false,\"addZeroRows\":false,\"withColumnMeta\":false,\"topCount\":0},\"focusOn\":\"Campaign\",\"projectParams\":{\"projectIds\":[]}},\"failInfo\":false}},{\"type\":206,\"payload\":{\"distribution\":\"space-between\",\"failInfo\":false}}],\"sugs\":[{\"content\":\"诊断账户\",\"prompt\":\"诊断账户\",\"api\":\"getNewDiagnosisInfo\",\"path\":\"aurora/GET/AixDiagnosisService/getNewDiagnosisInfo\",\"params\":\"{\\\"ids\\\":[630152],\\\"idType\\\":2,\\\"caseLevel\\\":[2,3]}\"},{\"content\":\"修改产品/服务描述\",\"prompt\":\"修改产品/服务描述\"},{\"content\":\"修改重点人群描述\",\"prompt\":\"修改重点人群描述\"},{\"content\":\"修改目标转化成本\",\"prompt\":\"修改目标转化成本\"},{\"content\":\"修改预算\",\"prompt\":\"修改预算\"},{\"content\":\"查看创意素材\",\"prompt\":\"查看创意素材\"}]},\"done\":true,\"scene\":3,\"tag\":0,\"agentContext\":{\"logInfo\":{\"raw\":[{\"intentType\":\"GET_CAMPAIGN\",\"operate\":\"GET\"}],\"rewrite\":{\"intentTypes\":[\"GET_CAMPAIGN\"],\"operate\":\"GET\"}},\"scene\":3}}}\n" - + "\n"; - ByteBuf byteBuf = Unpooled.wrappedBuffer(data.getBytes(StandardCharsets.UTF_8)); - HttpContent httpContent = new DefaultHttpContent(byteBuf); - - // part3 - LastHttpContent lastHttpContent = new DefaultLastHttpContent(); - - embeddedChannel.writeOutbound(httpResponse, httpContent, lastHttpContent); - - ByteBuf[] outputBufs = new ByteBuf[embeddedChannel.outboundMessages().size()]; - embeddedChannel.outboundMessages().toArray(outputBufs); - - // 构造了一份response的数据块儿 - ByteBuf outboundByteBuf = Unpooled.wrappedBuffer(outputBufs); - - // 把数据块儿分为 多份 - int count = 5; - int size_per_count = outboundByteBuf.readableBytes() / count; - - List byteBufList = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - if (i == count - 1) { - // 最后一份 取剩下所有的 - byteBufList.add( - outboundByteBuf.copy(i * size_per_count, outboundByteBuf.readableBytes() - i * size_per_count)); - } else { - byteBufList.add(outboundByteBuf.copy(i * size_per_count, size_per_count)); - } - } - // 分块儿完成 - - EmbeddedChannel channel = new EmbeddedChannel(new HttpSseResponseDecoderAdaptor()); - - RpcChannel rpcChannel = mock(RpcChannel.class); - when(rpcChannel.side()).thenReturn(ChannelSide.CLIENT); - when(rpcChannel.getAttribute(SSE_EMBEDDED_CHANNEL_KEY)).thenReturn(channel); - when(rpcChannel.getAttribute(SSE_REQUEST_ID_KEY)).thenReturn(-1L); - when(rpcChannel.getAttribute(PROTOCOL_KEY)).thenReturn(SpringRestSseProtocol.PROTOCOL_NAME); - - ChannelAttribute attribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - ThreadLocalChannelContext.getContext().setChannel(channel); - - List msgs = new ArrayList<>(); - DynamicCompositeByteBuf input = new DynamicCompositeByteBuf(); - SpringRestSseHttpDecoder springRestSseHttpDecoder = new SpringRestSseHttpDecoder(); - for (ByteBuf buf : byteBufList) { - input.addBuffer(buf.retain()); - try { - MsgBase msg = springRestSseHttpDecoder.decode(input); - if (msg != null) { - msgs.add((Response) msg); - } - } catch (Exception e) { - // ignore - e.printStackTrace(); - } - } - - List httpObjects = msgs.stream() - .flatMap(response -> ((List) response.getResult()).stream()).collect(Collectors.toList()); - - Assert.assertTrue(httpObjects.size() == 3); - Assert.assertTrue(httpObjects.get(0) instanceof HttpResponse); - Assert.assertTrue(httpObjects.get(1) instanceof HttpContent); - Assert.assertTrue(httpObjects.get(2) instanceof LastHttpContent); - - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/pom.xml b/starlight/starlight-protocol/starlight-protocol-stargate/pom.xml deleted file mode 100644 index 3db22003..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/pom.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight-protocol - 2025.0.1-SNAPSHOT - - - starlight-protocol-stargate - - diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoder.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoder.java deleted file mode 100644 index 43fcab3a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoder.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.serialization.serializer.DyuProtostuffSerializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Created by liuruisen on 2020/7/20. - */ -public class StargateDecoder implements ProtocolDecoder { - - private static final Logger LOGGER = LoggerFactory.getLogger(StargateDecoder.class); - - private static final ThreadLocal messageType = new ThreadLocal() { - @Override - protected String initialValue() { - return ""; - } - }; - - private static final String REQUEST = "request"; - private static final String RESPONSE = "response"; - - @Override - public MsgBase decode(DynamicCompositeByteBuf input) throws CodecException { - - if (input.readableBytes() < StargateProtocol.FIXED_LEN) { - throw new CodecException(CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION, - "Too little data to parse using stargate"); // wait and retry - } - - // NOTICE stargate协议中并没有magic num等能明确标识是本协议的字段, - ByteBuf head = input.retainedSlice(StargateProtocol.FIXED_LEN); - ByteBuf body = null; - MsgBase msgBase = null; - try { - int bodySize = 0; // bodySize - try { - bodySize = head.readInt(); - } catch (Exception e) { - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Cannot parse first 32bit of data flow to int value using stargate protocol," - + " maybe not bytes of stargate"); - } - - if (bodySize <= 0 || bodySize > StargateProtocol.MAX_BODY_SIZE) { - // if head.readInt > MAX_BODY_SIZE or head.readInt <= 0, - // we first think bytebuf is not stargate message. - // Considering maybe is not stargate data flow - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Body size is bigger than 512m or less than 1, maybe not bytes of stargate"); - } - // first byte of stargate data flow - if (head.readByte() != StargateProtocol.FIRST_BYTE_VALUE_OF_BODY) { - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "The first byte of data flow is not equals FIRST_BYTE_VALUE_OF_STARGATE_BODY," - + " not bytebuf of stargate"); - } - - if (input.readableBytes() < StargateProtocol.HEAD_LEN + bodySize) { - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTENOUGHDATA_EXCEPTION, - "Body Data not enough to parse using stargate"); // wait and retry - } - input.skipBytes(StargateProtocol.HEAD_LEN); // skip header size - - // body bytes - body = input.readRetainedSlice(bodySize); - byte[] bodyBytes = new byte[bodySize]; - body.readBytes(bodyBytes); - - // Prefer the last analyzed type, so we can improve performance - switch (messageType.get()) { - case REQUEST: - try { - return decodeRequest(bodyBytes); - } catch (CodecException e) { - messageType.set(""); - LOGGER.info("[Stargate messageTyp detect] " - + "The body data flow cannot be decoded as {stargate request}, " - + "will try decoded as stargate response"); - } - break; - case RESPONSE: - try { - return decodeResponse(bodyBytes); - } catch (CodecException e) { - messageType.set(""); - LOGGER.info("[Stargate messageType detect] " - + "The body data flow cannot be decoded as {stargate response}, " - + "will try decoded as stargate request"); - } - break; - } - - // try decode request - try { - msgBase = decodeRequest(bodyBytes); - messageType.set(REQUEST); - return msgBase; - } catch (CodecException e) { - LOGGER.info( - "[Stargate messageType detect] " + "The body data flow cannot be decoded as stargate request, " - + "will try decoded as stargate response, cause by {}", - e.getCause() == null ? e.getMessage() : e.getCause().getMessage()); - } - // try decode response - try { - msgBase = decodeResponse(bodyBytes); - messageType.set(RESPONSE); - return msgBase; - } catch (CodecException e) { - LOGGER.info( - "[Stargate messageType detect] " - + "The body data flow also cannot be decoded as stargate response, " - + "maybe not stargate messages or cannot deserialize, cause by {}", - e.getCause() == null ? e.getMessage() : e.getCause().getMessage()); - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "The body data flow neither cannot be decode as stargate response" - + " nor be decode as stargate response," - + " maybe not stargate messages or cannot deserialize"); - } - } finally { - head.release(); - if (body != null) { - body.release(); - } - } - } - - private Request decodeRequest(byte[] bodyBytes) { - StargateRequest stargateRequest = (StargateRequest) serializer().deserialize(bodyBytes, StargateRequest.class); - - if (StringUtils.isEmpty(stargateRequest.getId()) || StringUtils.isEmpty(stargateRequest.getMethodName()) - || stargateRequest.getUri() == null) { - throw new CodecException("Illegal message: stargate request's is or methodName or uri is empty"); - } - - URI uri = stargateRequest.getUri(); - ServiceConfig serviceConfig = new ServiceConfig(); - serviceConfig.setVersion(uri.getParameter(Constants.VERSION_KEY)); - serviceConfig.setGroup(uri.getParameter(Constants.GROUP_KEY)); - - Request request = new RpcRequest(); - request.setMethodName(stargateRequest.getMethodName()); - request.setServiceConfig(serviceConfig); - request.setParams(stargateRequest.getParameters()); - request.setParamsTypes(stargateRequest.getParameterTypes()); - request.setAttachmentKv(stargateRequest.getAttachments()); - request.setProtocolName(StargateProtocol.PROTOCOL_NAME); - if (request.getAttachmentKv() != null) { - // stargate id is string, but starlight id is long - // so we use kv map to restore stargate uuid - request.getAttachmentKv().put(Constants.STARGATE_UUID, stargateRequest.getId()); - } - // starlight not support group & version, so we use interfaceName to invoke - request.setServiceName(uri.getParameter(Constants.INTERFACE_KEY)); - - return request; - } - - private Response decodeResponse(byte[] bodyBytes) { - StargateResponse stargateResponse = - (StargateResponse) serializer().deserialize(bodyBytes, StargateResponse.class); - - if (StringUtils.isEmpty(stargateResponse.getId())) { - throw new CodecException("Illegal message: stargate response's id is empty"); - } - - Response response = new RpcResponse(Long.parseLong(stargateResponse.getId())); - response.setResult(stargateResponse.getResult()); - response.setProtocolName(StargateProtocol.PROTOCOL_NAME); - response.setAttachmentKv(stargateResponse.getAttachments()); - response.setStatus(Constants.SUCCESS_CODE); - if (stargateResponse.getException() != null) { - response.setErrorMsg("Server had occur exception: " + stargateResponse.getException().getMessage()); - response.setStatus(StarlightRpcException.BIZ_ERROR); - } - - return response; - } - - @Override - public void decodeBody(MsgBase msgBase) throws CodecException { - // do nothing, because we had done decode work completely in io thread - } - - private DyuProtostuffSerializer serializer() { - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(StargateProtocol.PROTOCOL_NAME); - return (DyuProtostuffSerializer) protocol.getSerialize(); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoder.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoder.java deleted file mode 100644 index 96f902e9..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoder.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.utils.GenericUtil; -import com.baidu.cloud.starlight.api.utils.NetUriUtils; -import com.baidu.cloud.starlight.serialization.serializer.DyuProtostuffSerializer; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcBizException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcExecutionException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcMethodNotFountException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcServiceNotFoundException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcSystemException; -import com.baidu.fengchao.stargate.remoting.exceptions.RpcTimeoutException; - -import java.util.HashMap; - -/** - * Created by liuruisen on 2020/7/20. Head is the lenght of body Body is {@link StargateResponse} or - * {@link StargateResponse} serialized bytes +--------------------------------------+-------------------+ + header | - * body | + 00000000 00000000 00000000 00000111 | 14 bytes body | + byte[3] byte[2] byte[1] byte[0] | message | - * +--------------------------------------+-------------------+ - */ -public class StargateEncoder implements ProtocolEncoder { - - /** - * Same as {@link StarlightRpcException#SERVICE_NOT_FOUND_EXCEPTION} - */ - private static final int SERVICE_NOT_FOUND_EXCEPTION = 1001; - - /** - * Same as {@link StarlightRpcException#METHOD_NOT_FOUND_EXCEPTION} - */ - private static final int METHOD_NOT_FOUND_EXCEPTION = 1002; - - /** - * Same as {@link StarlightRpcException#BAD_REQUEST} - */ - private static final int BAD_REQUEST = 1003; - - /** - * Same as {@link StarlightRpcException#TIME_OUT_EXCEPTION} - */ - private static final int TIME_OUT_EXCEPTION = 1008; - - /** - * Same as {@link StarlightRpcException#BIZ_ERROR} - */ - private static final int BIZ_ERROR = 2002; - - @Override - public ByteBuf encode(MsgBase input) throws CodecException { - if (input == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "MsgBase is null, cannot use stargate to encode"); - } - - if (input instanceof Request) { - Request request = (Request) input; - // head + body - return Unpooled.wrappedBuffer(stargateHeader(request.getBodyBytes().length), request.getBodyBytes()); - } - - if (input instanceof Response) { - Response response = (Response) input; - // head + body - return Unpooled.wrappedBuffer(stargateHeader(response.getBodyBytes().length), response.getBodyBytes()); - } - - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "MsgBase type is illegal {" + input.getClass().getName() + "}, cannot use stargate to encode"); - } - - @Override - public void encodeBody(MsgBase msgBase) throws CodecException { - if (msgBase == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "MsgBase is null, cannot use stargate to encode"); - } - - if (msgBase instanceof Request) { - encodeRequestBody((Request) msgBase); - } - - if (msgBase instanceof Response) { - encodeResponseBody((Response) msgBase); - } - } - - private void encodeRequestBody(Request request) { - if (request.getServiceConfig() == null) { - throw new CodecException(CodecException.PROTOCOL_ENCODE_EXCEPTION, - "Cannot use stargate to encode, group / version is null"); - } - // stargate uri: carries some necessary information - URI uri = new URI.Builder(StargateProtocol.PROTOCOL_NAME, NetUriUtils.getLocalHost(), 0) - .param(Constants.GROUP_KEY, request.getServiceConfig().getGroup()) // default is "normal" - .param(Constants.VERSION_KEY, request.getServiceConfig().getVersion()) // default is "1.0.0" - // serviceName can be interfaceName or generic target interfaceName - .param(Constants.INTERFACE_KEY, request.getServiceName()) - .param(Constants.GENERIC_KEY, GenericUtil.isGenericCall(request)) // support stargate generic filter - .build(); - - // starlight long type id will be cast to string as stargate String type id - StargateRequest stargateRequest = new StargateRequest(String.valueOf(request.getId()), uri, - request.getMethodName(), request.getParamsTypes(), request.getParams()); - - stargateRequest.setAttachments(new HashMap<>(request.getAttachmentKv())); - - byte[] bodyBytes = serializer().serialize(stargateRequest, StargateRequest.class); - request.setBodyBytes(bodyBytes); - } - - private void encodeResponseBody(Response response) { - StargateResponse stargateResponse = new StargateResponse(String.valueOf(response.getId())); - // when use original stargate client call starlight server,stargate uuid is string type and - // had be stored in request kv attachment by StargateDecoder#decodeRequest. - // so we retain the String type uuid and set it to StargateResponse#id - if (response.getRequest() != null && response.getRequest().getAttachmentKv() != null - && response.getRequest().getAttachmentKv().get(Constants.STARGATE_UUID) != null) { - stargateResponse.setId((String) response.getRequest().getAttachmentKv().get(Constants.STARGATE_UUID)); - } - - stargateResponse.setResult(response.getResult()); - stargateResponse.setAttachments(response.getAttachmentKv()); - if (response.getStatus() != Constants.SUCCESS_CODE) { - stargateResponse.setException(generateStargateException(response)); - } - byte[] bodyBytes = serializer().serialize(stargateResponse, StargateResponse.class); - response.setBodyBytes(bodyBytes); - } - - private DyuProtostuffSerializer serializer() { - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(StargateProtocol.PROTOCOL_NAME); - return (DyuProtostuffSerializer) protocol.getSerialize(); - } - - private byte[] stargateHeader(int bodyLength) { - return new byte[] {(byte) ((bodyLength >> 24) & 0xFF), (byte) ((bodyLength >> 16) & 0xFF), - (byte) ((bodyLength >> 8) & 0xFF), (byte) (bodyLength & 0xFF),}; - } - - /** - * 为使Starlight产生的异常可以被Stargate框架识别并展示出来,而增加的异常转换方法 - * - * @param response - * @return - */ - private RpcException generateStargateException(Response response) { - switch (response.getStatus()) { - case SERVICE_NOT_FOUND_EXCEPTION: - return new RpcServiceNotFoundException(response.getErrorMsg()); - case METHOD_NOT_FOUND_EXCEPTION: - return new RpcMethodNotFountException(response.getErrorMsg()); - case BAD_REQUEST: - return new RpcExecutionException(response.getErrorMsg()); - case TIME_OUT_EXCEPTION: - return new RpcTimeoutException(response.getErrorMsg()); - case BIZ_ERROR: - return new RpcBizException(response.getErrorMsg()); - default: - return new RpcSystemException(response.getErrorMsg()); - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocol.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocol.java deleted file mode 100644 index fd782a6b..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocol.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.serializer.DyuProtostuffSerializer; - -/** - * SPI name: stargate Created by liuruisen on 2020/7/20. - */ -public class StargateProtocol implements Protocol { - - static { - System.setProperty("protostuff.runtime.collection_schema_on_repeated_fields", "true"); - System.setProperty("protostuff.runtime.morph_collection_interfaces", "true"); - System.setProperty("protostuff.runtime.morph_map_interfaces", "true"); - } - - public static final String PROTOCOL_NAME = "stargate"; // stargate protocol name star - - protected static final int HEAD_LEN = 4; - - private static final DyuProtostuffSerializer serializer = new DyuProtostuffSerializer(); - - private static final StargateEncoder encoder = new StargateEncoder(); - - private static final StargateDecoder decoder = new StargateDecoder(); - - /** - * stargate header size is 4, first byte of body is 10d(key = 1, type Length-delimited), see - * protobuf key definition - */ - protected static final int FIXED_LEN = HEAD_LEN + 1; - - /** - * stargate first byte value of body is 10. protobuf key 定义 (field_number << 3) | wire_type 0000 1010 ==> - * 000 1010 (去掉最高位) ==> 0001 --> key 1 ==> 010 --> wire_type 2(Length-delimited) - */ - protected static final int FIRST_BYTE_VALUE_OF_BODY = 10; - - protected static final int MAX_BODY_SIZE = 512 * 1024 * 1024; // 512M - - @Override - public ProtocolEncoder getEncoder() { - return encoder; - } - - @Override - public ProtocolDecoder getDecoder() { - return decoder; - } - - @Override - public HeartbeatTrigger getHeartbeatTrigger() { - return null; - } - - @Override - public Serializer getSerialize() { - return serializer; - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequest.java deleted file mode 100644 index 7dc946f7..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.common.URI; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * Stargate Request model. Stargate uses it for serialization as protocol data. Created by liuruisen on 2020/7/20. - */ -public class StargateRequest { - - private String id; - - private String methodName; - - private Object[] parameters; - - private Class[] parameterTypes; - - private Map attachments; - - private URI uri; - - public StargateRequest(String id) { - this.id = id; - } - - public StargateRequest(String id, URI uri, String methodName, Class[] parameterTypes, Object[] parameters) { - this.uri = uri; - this.methodName = methodName; - this.id = id; - this.parameterTypes = parameterTypes; - this.parameters = parameters; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - public void setSerial(String serial) { - this.id = serial; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - public void setParameters(Object[] parameters) { - this.parameters = parameters; - } - - public void setParameterTypes(Class[] parameterTypes) { - this.parameterTypes = parameterTypes; - } - - public String getMethodName() { - return methodName; - } - - public Object[] getParameters() { - return parameters; - } - - public String getId() { - return id; - } - - public URI getUri() { - return uri; - } - - public Class[] getParameterTypes() { - return parameterTypes; - } - - public String toString() { - return "StargateRequest [methodName=" + methodName + ", parameterTypes=" + Arrays.toString(parameterTypes) - + ", parameters=" + Arrays.toString(parameters); - } - - public Map getAttachments() { - return attachments; - } - - public Object getAttachment(String key) { - if (attachments == null) { - return null; - } - return attachments.get(key); - } - - public void setAttachments(Map attachments) { - this.attachments = attachments == null ? new HashMap() : attachments; - } - - public void setAttachment(String key, Object value) { - if (attachments == null) { - attachments = new HashMap(); - } - attachments.put(key, value); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponse.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponse.java deleted file mode 100644 index b81de39c..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponse.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import java.util.HashMap; -import java.util.Map; - -/** - * Stargate Request model. Stargate uses it for serialization as protocol data. Created by liuruisen on 2020/7/20. - */ -public class StargateResponse { - - private String id; - - private Object exception; - - private Object result; - - private Map attachments; - - public StargateResponse(String id) { - this.id = id; - } - - public StargateResponse(String id, Object result, Throwable exception) { - this.id = id; - this.result = result; - // if (error != null && error instanceof Throwable) - // ((Throwable) error).initCause(null); - this.exception = exception; - } - - public Object getResult() { - return result; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Throwable getException() { - return (Throwable) exception; - } - - public boolean hasException() { - return exception != null; - } - - @Override - public String toString() { - return "StargateResponse [result=" + result + ", exception=" + exception + "]"; - } - - public void setException(Throwable exp) { - this.exception = exp; - } - - public void setResult(Object result) { - this.result = result; - } - - public Map getAttachments() { - return attachments; - } - - public Object getAttachment(String key) { - if (attachments == null) { - return null; - } - return attachments.get(key); - } - - public void setAttachments(Map attachments) { - this.attachments = attachments == null ? new HashMap() : attachments; - } - - public void setAttachment(String key, Object value) { - if (attachments == null) { - attachments = new HashMap(); - } - attachments.put(key, value); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarConfigException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarConfigException.java deleted file mode 100644 index 6fa4bf25..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarConfigException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.common.exceptions; - -public class StarConfigException extends StarException { - - private static final long serialVersionUID = -6247750979240276383L; - - public StarConfigException(String msg) { - super(msg); - } - - public StarConfigException(String msg, Throwable cause) { - super(msg, cause); - } - - public StarConfigException(Throwable cause) { - super(cause); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarException.java deleted file mode 100644 index 1d92e969..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/common/exceptions/StarException.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.common.exceptions; - -/** - * - * SystemException Base Exception Class - * - * @author liutao04@baidu.com - * - */ -public class StarException extends RuntimeException { - - private static final long serialVersionUID = 9008005083552195790L; - - public StarException() { - super(); - } - - public StarException(String message, Throwable cause) { - super(message, cause); - } - - public StarException(String message) { - super(message); - } - - public StarException(Throwable cause) { - super(cause); - } - - public String getMessage() { - return buildMessage(super.getMessage(), getCause()); - } - - public boolean contains(Class exType) { - if (exType == null) { - return false; - } - if (exType.isInstance(this)) { - return true; - } - Throwable cause = getCause(); - if (cause == this) { - return false; - } - while (cause != null) { - if (exType.isInstance(cause)) { - return true; - } - if (cause.getCause() == cause) { - break; - } - cause = cause.getCause(); - } - return false; - } - - public static String buildMessage(String message, Throwable cause) { - if (cause != null) { - StringBuilder sb = new StringBuilder(); - if (message != null) { - sb.append(message).append("; "); - } - sb.append("nested exception is ").append(cause); - return sb.toString(); - } else { - return message; - } - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcBizException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcBizException.java deleted file mode 100644 index 6ceda906..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcBizException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -/** - * Migrate from Stargate to support RpcBizException - * - * Service Bussiness Exception 上层服务抛出异常根节点 - * - * @author liutao04@baidu.com - * - */ -public class RpcBizException extends RpcException { - - private static final long serialVersionUID = 1354537638303414524L; - - public RpcBizException(String msg) { - super(msg); - } - - public RpcBizException(String msg, Throwable cause) { - super(msg, cause); - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcConnectionException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcConnectionException.java deleted file mode 100644 index a55cd606..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcConnectionException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -public class RpcConnectionException extends RpcSystemException { - private static final long serialVersionUID = 1927415247924574028L; - - public RpcConnectionException(String msg) { - super(msg); - } - - public RpcConnectionException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcException.java deleted file mode 100644 index cdc4c30a..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcException.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -import com.baidu.fengchao.stargate.common.exceptions.StarException; - -public class RpcException extends StarException { - - private static final long serialVersionUID = 8752574524257801163L; - - public RpcException() { - super(); - } - - public RpcException(String message, Throwable cause) { - super(message, cause); - } - - public RpcException(String message) { - super(message); - } - - public RpcException(Throwable cause) { - super(cause); - } - - public boolean contains(Class exType) { - if (exType == null) { - return false; - } - if (exType.isInstance(this)) { - return true; - } - Throwable cause = getCause(); - if (cause == this) { - return false; - } - if (cause instanceof RpcException) { - return ((RpcException) cause).contains(exType); - } else { - while (cause != null) { - if (exType.isInstance(cause)) { - return true; - } - if (cause.getCause() == cause) { - break; - } - cause = cause.getCause(); - } - return false; - } - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcExecutionException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcExecutionException.java deleted file mode 100644 index 2c4af436..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcExecutionException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -public class RpcExecutionException extends RpcSystemException { - private static final long serialVersionUID = 1927415247924574028L; - - public RpcExecutionException(String msg) { - super(msg); - } - - public RpcExecutionException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcLimitException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcLimitException.java deleted file mode 100644 index f5a8fb31..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcLimitException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -public class RpcLimitException extends RpcSystemException { - private static final long serialVersionUID = 1927415247924574028L; - - public RpcLimitException(String msg) { - super(msg); - } - - public RpcLimitException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcMethodNotFountException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcMethodNotFountException.java deleted file mode 100644 index 6eb2e10d..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcMethodNotFountException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -/** - * RpcMethodNotFountException - * - * @author zhaoyutong - * @version 1.0 - */ -public class RpcMethodNotFountException extends RpcSystemException { - - public RpcMethodNotFountException(String message, Throwable cause) { - super(message, cause); - } - - public RpcMethodNotFountException(String message) { - super(message); - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcServiceNotFoundException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcServiceNotFoundException.java deleted file mode 100644 index fd99d3ce..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcServiceNotFoundException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -/** - * RpcServiceNotFoundException - * - * @author zhaoyutong - * @version 1.0 - */ -public class RpcServiceNotFoundException extends RpcSystemException { - - public RpcServiceNotFoundException(String message, Throwable cause) { - super(message, cause); - } - - public RpcServiceNotFoundException(String message) { - super(message); - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcSystemException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcSystemException.java deleted file mode 100644 index b132ca47..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcSystemException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -/** - * - * RpcSystemException - * - * Rpc System Exception 框架级别异常的根节点 - * - * @author liutao04@baidu.com - * - */ -public class RpcSystemException extends RpcException { - - private static final long serialVersionUID = -1014545498815461908L; - - public RpcSystemException(String msg) { - super(msg); - } - - public RpcSystemException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcTimeoutException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcTimeoutException.java deleted file mode 100644 index 8fdc3f58..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/RpcTimeoutException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -public class RpcTimeoutException extends RpcSystemException { - private static final long serialVersionUID = 1927415247924574028L; - - public RpcTimeoutException(String msg) { - super(msg); - } - - public RpcTimeoutException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/UnknownRpcSystemException.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/UnknownRpcSystemException.java deleted file mode 100644 index 0790e6f5..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/java/com/baidu/fengchao/stargate/remoting/exceptions/UnknownRpcSystemException.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.fengchao.stargate.remoting.exceptions; - -/** - * - * RpcSystemException - * - * Rpc System Exception 框架级别异常的根节点 - * - * @author liutao04@baidu.com - * - */ -public class UnknownRpcSystemException extends RuntimeException { - - private static final long serialVersionUID = -1014545498815461908L; - - public UnknownRpcSystemException(String msg) { - super(msg); - } - - public UnknownRpcSystemException(String msg, Throwable cause) { - super(msg, cause); - } - - public UnknownRpcSystemException(Throwable cause) { - super(cause); - // TODO Auto-generated constructor stub - } - -} diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol b/starlight/starlight-protocol/starlight-protocol-stargate/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol deleted file mode 100644 index 2be372da..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.protocol.stargate.StargateProtocol \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoderTest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoderTest.java deleted file mode 100644 index 0d4698b5..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateDecoderTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Created by liuruisen on 2020/7/28. - */ -public class StargateDecoderTest { - - private StargateDecoder decoder = new StargateDecoder(); - - private StargateEncoder encoder = new StargateEncoder(); - - @Test - public void decodeRequest() { - Request request = new RpcRequest(); - request.setProtocolName(StargateProtocol.PROTOCOL_NAME); - request.setMethodName("method"); - request.setParams(new Object[] {"1313"}); - request.setParamsTypes(new Class[] {String.class}); - request.setServiceClass(StargateEncoder.class); - request.setServiceConfig(new ServiceConfig()); - - encoder.encodeBody(request); - - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - compositeByteBuf.addBuffer(encoder.encode(request)); - Assert.assertTrue(compositeByteBuf.readableBytes() > 0); - - MsgBase msgBase = decoder.decode(compositeByteBuf); - Assert.assertTrue(msgBase instanceof Request); - assertEquals(0, compositeByteBuf.readableBytes()); - Request request1 = (Request) msgBase; - assertEquals(StargateEncoder.class.getName(), request1.getServiceName()); - assertEquals("method", request1.getMethodName()); - } - - @Test - public void decodeResponse() { - Response response = new RpcResponse(); - response.setStatus(200); - response.setResult("Test"); - response.setRequest(new RpcRequest()); - - encoder.encodeBody(response); - - DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); - compositeByteBuf.addBuffer(encoder.encode(response)); - Assert.assertTrue(compositeByteBuf.readableBytes() > 0); - - MsgBase msgBase = decoder.decode(compositeByteBuf); - Assert.assertTrue(msgBase instanceof Response); - assertEquals(0, compositeByteBuf.readableBytes()); - - Response response1 = (Response) msgBase; - assertEquals(Constants.SUCCESS_CODE.intValue(), response1.getStatus()); - assertEquals("Test", response1.getResult()); - - Response errResponse = new RpcResponse(); - errResponse.setStatus(StarlightRpcException.BIZ_ERROR); - errResponse.setErrorMsg("Error"); - errResponse.setRequest(new RpcRequest()); - - encoder.encodeBody(errResponse); - compositeByteBuf.addBuffer(encoder.encode(errResponse)); - Assert.assertTrue(compositeByteBuf.readableBytes() > 0); - MsgBase msgBase2 = decoder.decode(compositeByteBuf); - Assert.assertTrue(msgBase2 instanceof Response); - assertEquals(0, compositeByteBuf.readableBytes()); - Response response2 = (Response) msgBase2; - assertEquals(StarlightRpcException.BIZ_ERROR.intValue(), response2.getStatus()); - assertTrue(response2.getErrorMsg().contains("Server had occur exception")); - } - - @Test - public void decodeBody() { - decoder.decodeBody(null); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoderTest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoderTest.java deleted file mode 100644 index bffb0714..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateEncoderTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.serialization.serializer.DyuProtostuffSerializer; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/7/27. - */ -public class StargateEncoderTest { - - private StargateEncoder encoder = new StargateEncoder(); - - private DyuProtostuffSerializer serializer = new DyuProtostuffSerializer(); - - @Test - public void encodeRequest() { - Request request = encodeRequestBody(); - ByteBuf byteBuf = encoder.encode(request); - byte[] fixBytes = new byte[5]; - byteBuf.readBytes(fixBytes); - Assert.assertEquals(fixBytes[4], 10); - } - - @Test - public void encodeError() { - // encode body null - Request request = null; - try { - encoder.encodeBody(request); - } catch (CodecException e) { - Assert.assertEquals(e.getCode(), CodecException.PROTOCOL_ENCODE_EXCEPTION); - } - - // stargate encode without group or version - request = new RpcRequest(); - try { - encoder.encodeBody(request); - } catch (CodecException e) { - Assert.assertEquals(e.getCode(), CodecException.PROTOCOL_ENCODE_EXCEPTION); - } - - // encode null - try { - encoder.encode(null); - } catch (CodecException e) { - Assert.assertEquals(e.getCode(), CodecException.PROTOCOL_ENCODE_EXCEPTION); - } - } - - @Test - public void encodeResponse() { - Response response = encodeResponseBody(); - ByteBuf byteBuf = encoder.encode(response); - byte[] fixBytes = new byte[5]; - byteBuf.readBytes(fixBytes); - Assert.assertEquals(fixBytes[4], 10); - } - - public Request encodeRequestBody() { - Request request = new RpcRequest(); - request.setProtocolName(StargateProtocol.PROTOCOL_NAME); - request.setMethodName("method"); - request.setParams(new Object[] {"1313"}); - request.setParamsTypes(new Class[] {String.class}); - request.setServiceClass(StargateEncoder.class); - request.setServiceConfig(new ServiceConfig()); - - encoder.encodeBody(request); - - byte[] requestBytes = request.getBodyBytes(); - Assert.assertNotNull(requestBytes); - Assert.assertTrue(request.getBodyBytes().length > 0); - - StargateRequest stargateRequest = (StargateRequest) serializer.deserialize(requestBytes, StargateRequest.class); - Assert.assertNotNull(stargateRequest); - Assert.assertEquals(stargateRequest.getMethodName(), "method"); - Assert.assertEquals(stargateRequest.getParameters()[0], "1313"); - Assert.assertEquals(stargateRequest.getUri().getParameter(Constants.GROUP_KEY), "normal"); - - return request; - } - - public Response encodeResponseBody() { - - Response response = new RpcResponse(); - response.setStatus(200); - response.setResult("Test"); - response.setRequest(new RpcRequest()); - - encoder.encodeBody(response); - - byte[] responseBytes = response.getBodyBytes(); - Assert.assertNotNull(responseBytes); - StargateResponse stargateResponse = - (StargateResponse) serializer.deserialize(responseBytes, StargateResponse.class); - Assert.assertNotNull(stargateResponse); - Assert.assertEquals(stargateResponse.getResult(), "Test"); - - Assert.assertNotNull(response.getBodyBytes()); - Assert.assertTrue(response.getBodyBytes().length > 0); - - Response errResponse = new RpcResponse(); - errResponse.setStatus(StarlightRpcException.BIZ_ERROR); - errResponse.setErrorMsg("Error"); - errResponse.setRequest(new RpcRequest()); - - encoder.encodeBody(errResponse); - - byte[] errResponseBytes = errResponse.getBodyBytes(); - Assert.assertNotNull(errResponseBytes); - StargateResponse errStargateResponse = - (StargateResponse) serializer.deserialize(errResponseBytes, StargateResponse.class); - Assert.assertNotNull(errStargateResponse); - Assert.assertNotNull(errStargateResponse.getException()); - Assert.assertEquals(errStargateResponse.getException().getMessage(), "Error"); - - return errResponse; - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocolTest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocolTest.java deleted file mode 100644 index 8a935d0c..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateProtocolTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.serialization.serializer.DyuProtostuffSerializer; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/7/27. - */ -public class StargateProtocolTest { - - private StargateProtocol stargateProtocol = new StargateProtocol(); - - @Test - public void getEncoder() { - Assert.assertTrue(stargateProtocol.getEncoder() instanceof StargateEncoder); - } - - @Test - public void getDecoder() { - Assert.assertTrue(stargateProtocol.getDecoder() instanceof StargateDecoder); - } - - @Test - public void getHeartbeatTrigger() { - Assert.assertNull(stargateProtocol.getHeartbeatTrigger()); - } - - @Test - public void getSerialize() { - Assert.assertTrue(stargateProtocol.getSerialize() instanceof DyuProtostuffSerializer); - } -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequestTest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequestTest.java deleted file mode 100644 index 7010d348..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateRequestTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import com.baidu.cloud.starlight.api.common.URI; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; - -/** - * Created by liuruisen on 2020/7/27. - */ -public class StargateRequestTest { - - @Test - public void requestTest() { - StargateRequest stargateRequest = new StargateRequest("123"); - URI uri = new URI.Builder("stargate", "127.0.0.1", 8888).build(); - stargateRequest.setUri(uri); - stargateRequest.setMethodName("method"); - stargateRequest.setParameters(new Object[] {"object"}); - stargateRequest.setParameterTypes(new Class[] {String.class}); - stargateRequest.setSerial("1"); - - Assert.assertEquals(stargateRequest.getUri(), uri); - Assert.assertEquals(stargateRequest.getId(), "1"); - Assert.assertEquals(stargateRequest.getMethodName(), "method"); - Assert.assertEquals(stargateRequest.getParameters().length, 1); - Assert.assertEquals(stargateRequest.getParameterTypes().length, 1); - - Assert.assertNull(stargateRequest.getAttachment("Key2")); - stargateRequest.setAttachment("Key2", "Value2"); - Assert.assertEquals(stargateRequest.getAttachment("Key2"), "Value2"); - - stargateRequest.setAttachments(new HashMap()); - Assert.assertEquals(stargateRequest.getAttachments().size(), 0); - - } - -} \ No newline at end of file diff --git a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponseTest.java b/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponseTest.java deleted file mode 100644 index 2c558e12..00000000 --- a/starlight/starlight-protocol/starlight-protocol-stargate/src/test/java/com/baidu/cloud/starlight/protocol/stargate/StargateResponseTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.protocol.stargate; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/7/27. - */ -public class StargateResponseTest { - - @Test - public void responseTest() { - StargateResponse stargateResponse = new StargateResponse("1"); - stargateResponse.setId("2"); - stargateResponse.setResult("Test"); - - Assert.assertEquals(stargateResponse.getId(), "2"); - Assert.assertEquals(stargateResponse.getResult(), "Test"); - Assert.assertNull(stargateResponse.getAttachments()); - Assert.assertNull(stargateResponse.getAttachment("Key")); - stargateResponse.setAttachment("Key", "Value"); - Assert.assertEquals(stargateResponse.getAttachment("Key"), "Value"); - stargateResponse.setException(new Exception()); - Assert.assertTrue(stargateResponse.hasException()); - Assert.assertTrue(stargateResponse.getException() instanceof Exception); - - StargateResponse stargateResponse1 = new StargateResponse("1", null, new Exception()); - stargateResponse1.setAttachments(null); - Assert.assertEquals(stargateResponse1.getAttachments().size(), 0); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/pom.xml b/starlight/starlight-serialization/pom.xml deleted file mode 100644 index f8dfbe65..00000000 --- a/starlight/starlight-serialization/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-serialization - - true - - - - com.baidu.cloud - starlight-api - ${project.version} - - - - com.google.protobuf - protobuf-java - 3.25.2 - - - - com.google.protobuf - protobuf-java-util - 3.25.2 - - - - diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompress.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompress.java deleted file mode 100644 index 10110fe7..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompress.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.compressor; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.compressor.Compress; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -/** - * GZip Compressor SPI name: gzip - */ -public class GzipCompress implements Compress { - - private static final Integer UNCOMPRESS_BYTE_SIZE = 256; - - @Override - public byte[] compress(byte[] inputByte) throws CodecException { - if (inputByte == null || inputByte.length == 0) { - return inputByte; - } - - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();) { - GZIPOutputStream gzipStream = new GZIPOutputStream(outputStream); - gzipStream.write(inputByte); - gzipStream.close(); - return outputStream.toByteArray(); - } catch (IOException e) { - throw new CodecException(CodecException.COMPRESS_EXCEPTION, "Gzip compress error: " + e.getMessage(), e); - } - } - - @Override - public byte[] decompress(byte[] inputByte) throws CodecException { - if (inputByte == null || inputByte.length == 0) { - return inputByte; - } - - try (ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(inputByte)) { - GZIPInputStream unGzip = new GZIPInputStream(in); - byte[] buffer = new byte[UNCOMPRESS_BYTE_SIZE]; - int n; - while ((n = unGzip.read(buffer)) >= 0) { - out.write(buffer, 0, n); - } - unGzip.close(); - return out.toByteArray(); - } catch (IOException e) { - throw new CodecException(CodecException.DECOMPRESS_EXCEPTION, "Gzip decompress error: " + e.getMessage(), - e); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompress.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompress.java deleted file mode 100644 index e5c89ee6..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompress.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.compressor; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.compressor.Compress; - -/** - * None compressor Return as is. Created by liuruisen on 2019-05-10. - */ -public class NoneCompress implements Compress { - - @Override - public byte[] compress(byte[] inputBytes) throws CodecException { - return inputBytes; - } - - @Override - public byte[] decompress(byte[] outputBytes) throws CodecException { - return outputBytes; - } -} diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializer.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializer.java deleted file mode 100644 index 72df0ef3..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializer.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.thirdparty.dyuprotostuff.LinkedBuffer; -import com.baidu.cloud.thirdparty.dyuprotostuff.ProtobufIOUtil; -import com.baidu.cloud.thirdparty.dyuprotostuff.Schema; -import com.baidu.cloud.thirdparty.dyuprotostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.dyuprotostuff.runtime.IdStrategy; -import com.baidu.cloud.thirdparty.dyuprotostuff.runtime.RuntimeSchema; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; - -import java.lang.reflect.Type; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Since Stargate uses the old version of Protostuff and is not compatible with the new version, we use two Serializers - * for processing stargate ser/deser Created by liuruisen on 2020/9/1. - */ -public class DyuProtostuffSerializer implements Serializer { - - private static final int DEFAULT_ALLOCATE_NUM = 512; - // Re-use (manage) this buffer to avoid allocating on every serialization - private ThreadLocal buffer = new ThreadLocal() { - @Override - protected LinkedBuffer initialValue() { - return LinkedBuffer.allocate(DEFAULT_ALLOCATE_NUM); - } - }; - - private Map idStrategyMap = new ConcurrentHashMap<>(); - - @Override - public byte[] serialize(Object obj, Type type) throws CodecException { - if (obj == null) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The message used to dyuprotostuff-serialize is null"); - } - - if (!(type instanceof Class)) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type to dyuprotostuff-serialize is not Class"); - } - - Class clazz = (Class) type; - if (!isSupported(clazz)) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type {" + type + "} used to dyuprotostuff-deserialize is illegal"); - } - - long starTime = System.currentTimeMillis(); - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(clazz, getIdStrategy()); - byte[] result = ProtobufIOUtil.toByteArray(obj, schema, buffer.get()); - LOGGER.debug("Serialize obj cost: {}", System.currentTimeMillis() - starTime); - return result; - } catch (Exception e) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "DyuProtostuff serialize error: " + e.getMessage(), e); - } finally { - buffer.get().clear(); - } - } - - @Override - public Object deserialize(byte[] bytes, Type type) throws CodecException { - if (bytes == null || bytes.length == 0) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The bytes used to dyuprotostuff deserializing are empty"); - } - - if (!(type instanceof Class)) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The type to dyuprotostuff deserializing is not Class"); - } - - Class clazz = (Class) type; - if (!isSupported(clazz)) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The type used to dyuprotostuff deserializing are illegal"); - } - long starTime = System.currentTimeMillis(); - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(clazz, getIdStrategy()); - Object content = schema.newMessage(); - ProtobufIOUtil.mergeFrom(bytes, content, schema); - LOGGER.debug("Serialize obj cost: {}", System.currentTimeMillis() - starTime); - return content; - } catch (Exception e) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "DyuProtostuff Deserialize error: " + e.getMessage(), e); - } - } - - private boolean isSupported(Class clazz) { - if (clazz == null) { - return false; - } - if (clazz.isPrimitive()) { - return false; - } - return true; - } - - private IdStrategy getIdStrategy() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - IdStrategy strategy = idStrategyMap.get(classLoader); - if (strategy == null) { - idStrategyMap.putIfAbsent(classLoader, new DefaultIdStrategy()); - strategy = idStrategyMap.get(classLoader); - } - return strategy; - } -} diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializer.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializer.java deleted file mode 100644 index e55848a5..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.thirdparty.jackson.annotation.JsonInclude; -import com.baidu.cloud.thirdparty.jackson.databind.DeserializationFeature; -import com.baidu.cloud.thirdparty.jackson.databind.JavaType; -import com.baidu.cloud.thirdparty.jackson.databind.ObjectMapper; -import com.baidu.cloud.thirdparty.jackson.databind.SerializationFeature; -import com.baidu.cloud.thirdparty.jackson.databind.type.TypeFactory; -import com.baidu.cloud.thirdparty.jackson.datatype.jsr310.JavaTimeModule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Type; -import java.text.SimpleDateFormat; - -/** - * Json Serializer based on jackson. Created by liuruisen on 2020/5/27. - */ -public class JsonSerializer implements Serializer { - - private static final Logger LOGGER = LoggerFactory.getLogger(JsonSerializer.class); - - public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - static { - // 序列化的时候序列对象的所有属性 - OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS); - - // 反序列化的时候如果多了其他属性,不抛出异常 - OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - // 如果是空对象的时候,不抛异常 - OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - - // 取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式 - OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - OBJECT_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); - OBJECT_MAPPER.registerModule(new JavaTimeModule()); - } - - @Override - public byte[] serialize(Object obj, Type type) throws CodecException { - if (obj == null) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, "The message used to json-serialize is null"); - } - try { - return OBJECT_MAPPER.writeValueAsBytes(obj); // json string + utf8 encode - } catch (Throwable e) { - LOGGER.error("JsonSerializer bodySerialize fail: ", e); - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, "Json serialize error: " + e.getMessage(), e); - } - } - - @Override - public Object deserialize(byte[] bytes, Type type) throws CodecException { - - if (bytes == null || bytes.length == 0) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The bytes used to json deserialize are empty"); - } - - try { - return OBJECT_MAPPER.readValue(bytes, getJavaType(type)); - } catch (Throwable e) { - LOGGER.error("JsonSerializer bodyDeserialize fail: ", e); - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, "Json deserialize error: " + e.getMessage(), - e); - } - } - - private JavaType getJavaType(Type type) { - TypeFactory typeFactory = OBJECT_MAPPER.getTypeFactory(); - return typeFactory.constructType(type); - } - -} diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializer.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializer.java deleted file mode 100644 index 7b8e2428..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializer.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.utils.SerializationUtils; -import com.baidu.cloud.thirdparty.protostuff.LinkedBuffer; -import com.baidu.cloud.thirdparty.protostuff.ProtobufIOUtil; -import com.baidu.cloud.thirdparty.protostuff.Schema; -import com.baidu.cloud.thirdparty.protostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.IdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.RuntimeSchema; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Type; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Support serialize pojo at runtime , Used to serializer/deserializer in runtime without defining proto file Created by - * liuruisen on 2020/2/20. - */ -public class ProtoStuffSerializer implements Serializer { - private static final Logger LOGGER = LoggerFactory.getLogger(ProtoStuffSerializer.class); - - private static final int DEFAULT_ALLOCATE_NUM = 512; - // Re-use (manage) this buffer to avoid allocating on every serialization - private ThreadLocal buffer = new ThreadLocal() { - @Override - protected LinkedBuffer initialValue() { - return LinkedBuffer.allocate(DEFAULT_ALLOCATE_NUM); - } - }; - - private final Map> idStrategyMap = new ConcurrentHashMap<>(); - - @Override - public byte[] serialize(Object obj, Type type) throws CodecException { - return serialize(obj, type, IdStrategy.DEFAULT_FLAGS); - } - - /** - * Support specified idstrategy, used in brpc - * - * @param obj - * @param type - * @param strategyFlag - * @return - * @throws CodecException - */ - public byte[] serialize(Object obj, Type type, Integer strategyFlag) throws CodecException { - - if (obj == null) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The message used to protostuff-serialize is null"); - } - - if (!(type instanceof Class)) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type to protostuff-serialize is not Class"); - } - - Class clazz = (Class) type; - if (!isSupported(clazz)) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type {" + type + "} used to protostuff-deserialize is illegal"); - } - - long starTime = System.currentTimeMillis(); - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(clazz, getIdStrategy(strategyFlag)); // schema will be cached - byte[] result = ProtobufIOUtil.toByteArray(obj, schema, buffer.get()); - LOGGER.debug("Serialize obj cost: {}", System.currentTimeMillis() - starTime); - return result; - } catch (Throwable e) { - CodecException exception = SerializationUtils.convertToCodecException(e, CodecException.SERIALIZE_EXCEPTION, - "Protostuff serialize error"); - LOGGER.error("Serialize error, ", e); - throw exception; - } finally { - - buffer.get().clear(); - } - } - - @Override - public Object deserialize(byte[] bytes, Type type) throws CodecException { - - return deserialize(bytes, type, IdStrategy.DEFAULT_FLAGS); - } - - /** - * Support specified idstrategy, used in brpc - * - * @param bytes - * @param type - * @param strategyFlag - * @return - * @throws CodecException - */ - public Object deserialize(byte[] bytes, Type type, Integer strategyFlag) throws CodecException { - - if (bytes == null || bytes.length == 0) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The bytes used to protostuff deserializing are empty"); - } - - if (!(type instanceof Class)) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The type to protostuff deserializing is not Class"); - } - - Class clazz = (Class) type; - if (!isSupported(clazz)) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The type used to protostuff deserializing are illegal"); - } - long starTime = System.currentTimeMillis(); - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(clazz, getIdStrategy(strategyFlag)); // schema will be cached - Object content = schema.newMessage(); - ProtobufIOUtil.mergeFrom(bytes, content, schema); - LOGGER.debug("Deserialize obj cost: {}", System.currentTimeMillis() - starTime); - return content; - } catch (Throwable e) { - CodecException exception = SerializationUtils.convertToCodecException(e, - CodecException.DESERIALIZE_EXCEPTION, "Protostuff Deserialize error"); - LOGGER.error("Deserialize error, ", e); - throw exception; - } - } - - private boolean isSupported(Class clazz) { - if (clazz == null) { - return false; - } - if (clazz.isPrimitive()) { - return false; - } - return true; - } - - /** - * 将IdStrategy与ClassLoader关联起来 其原因是, <1> IdStrategy中缓存了很多类的Schema信息,这些信息与ClassLoader关联的 <2> - * hairuo场景中存在多个ClassLoader的场景 因而为适应海若场景的使用,需要做关联 - * - * @param strategyFlag - * @return - */ - private IdStrategy getIdStrategy(Integer strategyFlag) { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Map strategies = idStrategyMap.get(classLoader); - - if (strategies == null) { - idStrategyMap.putIfAbsent(classLoader, new ConcurrentHashMap<>()); - strategies = idStrategyMap.get(classLoader); - } - - IdStrategy idStrategy = strategies.get(strategyFlag); - - if (idStrategy == null) { - // 重点为此处,通过new DefaultIdStrategy的方式,将classloader与DefaultIdStrategy关联起来 - strategies.putIfAbsent(strategyFlag, new DefaultIdStrategy(strategyFlag)); - idStrategy = strategies.get(strategyFlag); - } - - return idStrategy; - } -} diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtobufSerializer.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtobufSerializer.java deleted file mode 100644 index 2dd67c53..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/serializer/ProtobufSerializer.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.utils.SerializationUtils; -import com.google.protobuf.Message; -import com.google.protobuf.MessageLite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -/** - * 原生protobuf-java的序列化和反序列化类 使用brpc协议时支持业务使用.proto文件定义类对象 - */ -public class ProtobufSerializer implements Serializer { - - private static final Logger LOGGER = LoggerFactory.getLogger(ProtobufSerializer.class); - - @Override - public byte[] serialize(Object inputObj, Type type) throws CodecException { - if (inputObj == null) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The message used to protobuf serializing is null"); - } - if (inputObj.getClass() != type || !isSupported(inputObj.getClass())) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type used to protobuf serializing is illegal"); - } - - try { - return ((Message) inputObj).toByteArray(); - } catch (Throwable e) { - CodecException codecException = SerializationUtils.convertToCodecException(e, - CodecException.SERIALIZE_EXCEPTION, "Protobuf serialize error"); - LOGGER.error("Protobuf deserialize error, ", codecException); - throw codecException; - } - } - - @Override - public Object deserialize(byte[] bytes, Type type) throws CodecException { - if (bytes == null || bytes.length == 0) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The bytes used to protobuf deserializing are empty"); - } - - if (!(type instanceof Class)) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "The type to protobuf deserializing is not Class"); - } - - Class clazz = (Class) type; - if (!isSupported(clazz)) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "The type used to protobuf deserializing are illegal"); - } - - try { - Method outputParseFromMethod = clazz.getMethod("parseFrom", byte[].class); - return outputParseFromMethod.invoke(type, bytes); - } catch (Throwable e) { - CodecException codecException = SerializationUtils.convertToCodecException(e, - CodecException.DESERIALIZE_EXCEPTION, "Protobuf deserialize error"); - LOGGER.error("Protobuf deserialize error, ", codecException); - throw codecException; - } - } - - private boolean isSupported(Class clazz) { - if (clazz == null) { - return false; - } - - if (MessageLite.class.isAssignableFrom(clazz)) { - return true; - } - return false; - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/utils/SerializationUtils.java b/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/utils/SerializationUtils.java deleted file mode 100644 index 29d9c2ea..00000000 --- a/starlight/starlight-serialization/src/main/java/com/baidu/cloud/starlight/serialization/utils/SerializationUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.utils; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.utils.StringUtils; - -public class SerializationUtils { - - public static CodecException convertToCodecException(Throwable throwable, Integer errorCode, String errMsgPrefix) { - StringBuilder errMsgSb = new StringBuilder(errMsgPrefix); - - // parent error detail - errMsgSb.append(", error detail: "); - errMsgSb.append(throwable.getClass().getName()); - if (!StringUtils.isEmpty(throwable.getMessage())) { - errMsgSb.append(", "); - errMsgSb.append(throwable.getMessage()); - } - - errMsgSb.append(" "); - - // cause error detail - Throwable cause = throwable.getCause(); - if (cause != null) { - errMsgSb.append("caused by: "); - errMsgSb.append(cause.getClass().getName()); - errMsgSb.append(", "); - errMsgSb.append(cause.getMessage()); - } - - return new CodecException(errorCode, errMsgSb.toString(), throwable); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.serialization.compressor.Compress b/starlight/starlight-serialization/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.serialization.compressor.Compress deleted file mode 100644 index 01d1e869..00000000 --- a/starlight/starlight-serialization/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.serialization.compressor.Compress +++ /dev/null @@ -1,2 +0,0 @@ -com.baidu.cloud.starlight.serialization.compressor.GzipCompress -com.baidu.cloud.starlight.serialization.compressor.NoneCompress \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompressTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompressTest.java deleted file mode 100644 index 1f8210af..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/GzipCompressTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.compressor; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/9/10. - */ -public class GzipCompressTest { - - private GzipCompress gzipCompress = new GzipCompress(); - private byte[] origin = "Hello".getBytes(); - - @Test - public void compress() { - byte[] compress = gzipCompress.compress(origin); - Assert.assertFalse(Arrays.equals(origin, compress)); - } - - @Test - public void compressExp() { - // input null - byte[] compress = gzipCompress.compress(null); - Assert.assertTrue(compress == null); - - byte[] compress2 = gzipCompress.compress(new byte[0]); - Assert.assertTrue(compress2.length == 0); - - } - - @Test - public void decompress() { - byte[] compress = gzipCompress.compress(origin); - byte[] bytes = gzipCompress.decompress(compress); - Assert.assertTrue(Arrays.equals(bytes, origin)); - } - - @Test - public void decompressExp() { - // decompress null - byte[] bytes = gzipCompress.decompress(null); - Assert.assertTrue(bytes == null); - - // length 0 - byte[] bytes2 = gzipCompress.decompress(new byte[0]); - Assert.assertTrue(bytes2.length == 0); - - byte[] byte3 = new byte[10]; - System.arraycopy("123".getBytes(), 0, byte3, 0, "123".getBytes().length); - try { - gzipCompress.decompress(byte3); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DECOMPRESS_EXCEPTION); - } - } - -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompressTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompressTest.java deleted file mode 100644 index 6df77824..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/compressor/NoneCompressTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.compressor; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; - -import static org.junit.Assert.*; - -/** - * Created by liuruisen on 2020/9/10. - */ -public class NoneCompressTest { - - private byte[] input = "Hello".getBytes(); - private NoneCompress noneCompress = new NoneCompress(); - - @Test - public void compress() { - byte[] compress = noneCompress.compress(input); - Assert.assertTrue(Arrays.equals(compress, input)); - } - - @Test - public void decompress() { - byte[] unCompress = noneCompress.decompress(input); - Assert.assertTrue(Arrays.equals(input, unCompress)); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/BizModelTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/BizModelTest.java deleted file mode 100644 index e3a48958..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/BizModelTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.serialization.serializer.model.BasePageRequestDto; -import com.baidu.cloud.starlight.serialization.serializer.model.OrderBy; -import com.baidu.cloud.thirdparty.google.common.collect.Lists; -import org.junit.Test; - -import java.util.Arrays; - -/** - * Created by liuruisen on 2021/2/4. - */ -public class BizModelTest extends NewProtostuffSerializeTest { - - @Test - public void basePageRequestDto() { - BasePageRequestDto basePageRequestDto = new BasePageRequestDto(26L, "TOKEN"); - basePageRequestDto.setPageNo(1); - basePageRequestDto.setPageSize(10000); - basePageRequestDto.setOrderBys(Lists.newArrayList(new OrderBy("id", OrderBy.OrderType.ASC))); - - byte[] nullBytes = serialize(basePageRequestDto, BasePageRequestDto.class, nullStrategy); - System.out.println(Arrays.toString(nullBytes)); - - BasePageRequestDto requestDto = - (BasePageRequestDto) deserialize(nullBytes, BasePageRequestDto.class, nullStrategy); - System.out.println(requestDto); - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/CompatibleTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/CompatibleTest.java deleted file mode 100644 index a6c8d8a0..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/CompatibleTest.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.serialization.serializer.model.Address; -import com.baidu.cloud.starlight.serialization.serializer.model.ExtInfo; -import com.baidu.cloud.starlight.serialization.serializer.model.Sex; -import com.baidu.cloud.starlight.serialization.serializer.model.User; -import com.baidu.cloud.thirdparty.protostuff.LinkedBuffer; -import com.baidu.cloud.thirdparty.protostuff.ProtobufIOUtil; -import com.baidu.cloud.thirdparty.protostuff.Schema; -import com.baidu.cloud.thirdparty.protostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.IdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.RuntimeSchema; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * 测试不同参数配置下的兼容性 1. 0 参数配置,默认场景 2. 3 参数配置,stargate场景 3. 5 参数配置, Created by liuruisen on 2021/1/19. - */ -public class CompatibleTest { - - private IdStrategy defaultStrategy; - - private IdStrategy newly3Strategy; - - private IdStrategy newlyStrategy; - - private IdStrategy nullStrategy; - - private User user; - - @Before - public void before() { - - defaultStrategy = new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS); - - newly3Strategy = - new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS | IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS - | IdStrategy.MORPH_COLLECTION_INTERFACES | IdStrategy.MORPH_MAP_INTERFACES); - - newlyStrategy = new DefaultIdStrategy( - IdStrategy.DEFAULT_FLAGS | IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.MORPH_COLLECTION_INTERFACES - | IdStrategy.MORPH_MAP_INTERFACES | IdStrategy.MORPH_NON_FINAL_POJOS); - - nullStrategy = new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS | IdStrategy.PRESERVE_NULL_ELEMENTS); - - user = new User(); - user.setUserName("Test-user"); - user.setUserId(123L); - user.setAge(18); - user.setAlive(true); - user.setBalance(11111.333d); - user.setInfo("This is a human"); - user.setSalary(200.67f); - user.setSex(Sex.MALE); - - Address address = new Address("Beijing"); - user.setAddress(address); - - user.setTags(Arrays.asList("Key=Value", "Key2=Value2")); - - TreeSet stringSet = new TreeSet<>(); - stringSet.add("val1"); - stringSet.add("val2"); - user.setSet(stringSet); - - ExtInfo extInfo1 = new ExtInfo("ext1", 123); - ExtInfo extInfo2 = new ExtInfo("ext2", "test"); - LinkedList extInfos = new LinkedList<>(); - extInfos.add(extInfo1); - extInfos.add(extInfo2); - user.setExtInfos(extInfos); - - Object[] arrays = new Object[3]; - arrays[0] = 123; - arrays[1] = address; - arrays[2] = Sex.NONE; - - user.setArray(arrays); - - } - - @Test - public void serializeCompatibleFullMsg() { - System.out.println("--- Full msg compatible ---"); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleEmptyList() { - System.out.println("--- Empty list compatible ---"); - user.setTags(Collections.emptyList()); - serializeCompatible(user); - - user.setTags(new ArrayList<>()); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleEmptySet() { - System.out.println("--- Empty set compatible ---"); - user.setSet(new TreeSet<>()); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleEmptyArray() { - System.out.println("--- Empty array compatible ---"); - user.setArray(new Object[] {}); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleListMiddNull() { - System.out.println("--- List middle null compatible ---"); - user.setTags(Arrays.asList("1", null, "3")); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleSetMiddNull() { - System.out.println("--- Set middle null compatible ---"); - try { - TreeSet set = new TreeSet<>(); - set.add("1"); - set.add(null); - set.add("3"); - user.setSet(set); - serializeCompatible(user); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void serializeCompatibleArrayMiddNull() { - System.out.println("--- Array middle null compatible ---"); - Object[] arrsy = new Object[3]; - arrsy[0] = 1; - arrsy[1] = null; - arrsy[2] = "hello"; - user.setArray(arrsy); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleSubList() { - System.out.println("--- Sub list compatible ---"); - List stringList = Arrays.asList("1", "2", "3", "4", "5"); - user.setTags(stringList.subList(0, 2)); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleMapKeySet() { - System.out.println("--- Map keyset compatible ---"); - Map map = new HashMap<>(); - map.put("1", "1"); - map.put("2", "2"); - map.put("3", "3"); - TreeSet treeSet = new TreeSet(); - treeSet.addAll(map.keySet()); - user.setSet(treeSet); - serializeCompatible(user); - } - - @Test - public void serializeCompatibleMiddleNull() { - System.out.println("--- Middle null compatible ---"); - user.setAddress(null); - serializeCompatible(user); - } - - @Test - public void serializeSubListWithNUllStrategy() { - System.out.println("--- Sub List with null strategy compatible ---"); - List stringList = Arrays.asList("1", "2", "3", "4", "5"); - user.setTags(stringList.subList(0, 2)); - - byte[] nullSerBytes = serialize(user, User.class, nullStrategy); - User result = (User) deserialize(nullSerBytes, User.class, nullStrategy); - System.out.println("null ser - null deser : " + user.equals(result)); - } - - @Test - public void serializeKeySetWithNUllStrategy() { - System.out.println("--- key set with null strategy compatible ---"); - Map map = new HashMap<>(); - map.put("1", "1"); - map.put("2", "2"); - map.put("3", "3"); - TreeSet treeSet = new TreeSet(); - treeSet.addAll(map.keySet()); - user.setSet(treeSet); - - byte[] nullSerBytes = serialize(user, User.class, nullStrategy); - User result = (User) deserialize(nullSerBytes, User.class, nullStrategy); - System.out.println("null ser - null deser : " + user.equals(result)); - } - - protected void serializeCompatible(User user) { - // serialize - byte[] defaultSerBytes = serialize(user, User.class, defaultStrategy); - assertNotNull(defaultSerBytes); - assertTrue(defaultSerBytes.length > 0); - System.out.println("Default bytes " + Arrays.toString(defaultSerBytes)); - System.out.println(""); - - byte[] newly3SerBytes = serialize(user, User.class, newly3Strategy); - assertNotNull(newly3SerBytes); - assertTrue(newly3SerBytes.length > 0); - System.out.println("Newly3 bytes " + Arrays.toString(newly3SerBytes)); - System.out.println(""); - - byte[] newlySerBytes = serialize(user, User.class, newlyStrategy); - assertNotNull(newlySerBytes); - assertTrue(newlySerBytes.length > 0); - System.out.println("Newly bytes " + Arrays.toString(newlySerBytes)); - System.out.println(""); - - byte[] nullBytes = serialize(user, User.class, nullStrategy); - assertNotNull(nullBytes); - assertTrue(nullBytes.length > 0); - System.out.println("Null bytes " + Arrays.toString(nullBytes)); - System.out.println(""); - - // deserialize - try { - User defaultUser = (User) deserialize(defaultSerBytes, User.class, defaultStrategy); - assertNotNull(defaultUser); - System.out.println("default ser - default deser : " + user.equals(defaultUser)); - } catch (CodecException e) { - System.out.println("Use default strategy to deserialize default bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User threeUser = (User) deserialize(newly3SerBytes, User.class, newly3Strategy); - assertNotNull(threeUser); - System.out.println("newly3 ser - newly3 deser : " + user.equals(threeUser)); - } catch (CodecException e) { - System.out.println("Use newly3 strategy to deserialize newly3 bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User fiveUser = (User) deserialize(newlySerBytes, User.class, newlyStrategy); - assertNotNull(fiveUser); - System.out.println("newly ser - newly deser : " + user.equals(fiveUser)); - } catch (CodecException e) { - System.out.println("Use newly strategy to deserialize newly bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User nullUser = (User) deserialize(nullBytes, User.class, nullStrategy); - assertNotNull(nullUser); - System.out.println("null ser - null deser : " + user.equals(nullUser)); - } catch (CodecException e) { - System.out.println("Use null strategy to deserialize null bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - // deserialize compatible - try { - User useNewly3StrategyToDesDefBytes = (User) deserialize(defaultSerBytes, User.class, newly3Strategy); - assertNotNull(useNewly3StrategyToDesDefBytes); - System.out.println("default ser - newly3 deser : " + user.equals(useNewly3StrategyToDesDefBytes)); - } catch (CodecException e) { - System.out.println("Use newly3 strategy to deserialize default bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNewlyStrategyToDesDefBytes = (User) deserialize(defaultSerBytes, User.class, newlyStrategy); - assertNotNull(useNewlyStrategyToDesDefBytes); - System.out.println("default ser - newly deser : " + user.equals(useNewlyStrategyToDesDefBytes)); - } catch (CodecException e) { - System.out.println("Use newly strategy to deserialize default bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNullStrategyToDesDefBytes = (User) deserialize(defaultSerBytes, User.class, nullStrategy); - assertNotNull(useNullStrategyToDesDefBytes); - System.out.println("default ser - null deser : " + user.equals(useNullStrategyToDesDefBytes)); - } catch (CodecException e) { - System.out.println("Use null strategy to deserialize default bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNewly3StraToDesNewBytes = (User) deserialize(newlySerBytes, User.class, newly3Strategy); - assertNotNull(useNewly3StraToDesNewBytes); - System.out.println("newly ser - newly3 deser : " + user.equals(useNewly3StraToDesNewBytes)); - } catch (CodecException e) { - System.out.println("Use newly3 strategy to deserialize newly bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useDefStraToDesNewBytes = (User) deserialize(newlySerBytes, User.class, defaultStrategy); - assertNotNull(useDefStraToDesNewBytes); - System.out.println("newly ser - default deser : " + user.equals(useDefStraToDesNewBytes)); - } catch (CodecException e) { - System.out.println("Use default strategy to deserialize newly bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNullStraToDesNewBytes = (User) deserialize(newlySerBytes, User.class, nullStrategy); - assertNotNull(useNullStraToDesNewBytes); - System.out.println("newly ser - null deser : " + user.equals(useNullStraToDesNewBytes)); - } catch (CodecException e) { - System.out.println("Use null strategy to deserialize newly bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useDefStraToDesNewly3Bytes = (User) deserialize(newly3SerBytes, User.class, defaultStrategy); - assertNotNull(useDefStraToDesNewly3Bytes); - System.out.println("newly3 ser - default deser : " + user.equals(useDefStraToDesNewly3Bytes)); - } catch (CodecException e) { - System.out.println("Use default strategy to deserialize newly3 bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNewStraToDesNewly3Bytes = (User) deserialize(newly3SerBytes, User.class, newlyStrategy); - assertNotNull(useNewStraToDesNewly3Bytes); - System.out.println("newly3 ser - newly deser : " + user.equals(useNewStraToDesNewly3Bytes)); - } catch (CodecException e) { - System.out.println("Use newly strategy to deserialize newly3 bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNullStraToDesNewly3Bytes = (User) deserialize(newly3SerBytes, User.class, nullStrategy); - assertNotNull(useNullStraToDesNewly3Bytes); - System.out.println("newly3 ser - null deser : " + user.equals(useNullStraToDesNewly3Bytes)); - } catch (CodecException e) { - System.out.println("Use null strategy to deserialize newly3 bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useDefStraToDesNullBytes = (User) deserialize(nullBytes, User.class, defaultStrategy); - assertNotNull(useDefStraToDesNullBytes); - System.out.println("null ser - default deser : " + user.equals(useDefStraToDesNullBytes)); - } catch (CodecException e) { - System.out.println("Use default strategy to deserialize null bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNew3StraToDesNullBytes = (User) deserialize(nullBytes, User.class, newly3Strategy); - assertNotNull(useNew3StraToDesNullBytes); - System.out.println("null ser - new3 deser : " + user.equals(useNew3StraToDesNullBytes)); - } catch (CodecException e) { - System.out.println("Use new3 strategy to deserialize null bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - try { - User useNewStraToDesNullBytes = (User) deserialize(nullBytes, User.class, newlyStrategy); - assertNotNull(useNewStraToDesNullBytes); - System.out.println("null ser - newly deser : " + user.equals(useNewStraToDesNullBytes)); - } catch (CodecException e) { - System.out.println("Use newly strategy to deserialize null bytes failed, causeb by " + e.getMessage()); - e.printStackTrace(); - } - System.out.println(""); - - } - - private static final int DEFAULT_ALLOCATE_NUM = 512; - // Re-use (manage) this buffer to avoid allocating on every serialization - private ThreadLocal buffer = new ThreadLocal() { - @Override - protected LinkedBuffer initialValue() { - return LinkedBuffer.allocate(DEFAULT_ALLOCATE_NUM); - } - }; - - private Object deserialize(byte[] bytes, Class type, IdStrategy idStrategy) throws CodecException { - - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(type, idStrategy); // schema will be cached - Object content = schema.newMessage(); - ProtobufIOUtil.mergeFrom(bytes, content, schema); - return content; - } catch (Exception e) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "Protostuff Deserialize error: " + e.getMessage(), e); - } - } - - private byte[] serialize(Object obj, Class type, IdStrategy idStrategy) throws CodecException { - - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(type, idStrategy); // schema will be cached - return ProtobufIOUtil.toByteArray(obj, schema, buffer.get()); - } catch (Exception e) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "Protostuff serialize error: " + e.getMessage(), e); - } finally { - buffer.get().clear(); - } - } - -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializerTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializerTest.java deleted file mode 100644 index be9ce4ea..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/DyuProtostuffSerializerTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/9/1. - */ -public class DyuProtostuffSerializerTest { - - private DyuProtostuffSerializer serializer = new DyuProtostuffSerializer(); - - @Test - public void testSerialize() { - byte[] bytes1 = serializer.serialize("Test", String.class); - String str = (String) serializer.deserialize(bytes1, String.class); - Assert.assertTrue(str.equals("Test")); - - } - - @Test - public void testSerializeError() { - try { - // message null - serializer.serialize(null, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.SERIALIZE_EXCEPTION); - } - - try { - // type null - serializer.serialize("123", null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.SERIALIZE_EXCEPTION); - } - - try { - // not support single long int boolean - serializer.serialize(1l, long.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.SERIALIZE_EXCEPTION); - } - - try { - // serialize exception - serializer.serialize(1, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.SERIALIZE_EXCEPTION); - } - } - - @Test - public void testDeserializeError() { - try { - // bytes null - serializer.deserialize(null, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DESERIALIZE_EXCEPTION); - } - - try { - // bytes length 0 - serializer.deserialize(new byte[0], String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DESERIALIZE_EXCEPTION); - } - - byte[] bytes1 = serializer.serialize(1, Integer.class); - try { - // type null - serializer.deserialize(bytes1, null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DESERIALIZE_EXCEPTION); - } - - try { - // type isPrimitive - serializer.deserialize(bytes1, int.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DESERIALIZE_EXCEPTION); - } - - try { - // deserialize exception - serializer.deserialize(bytes1, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode() == CodecException.DESERIALIZE_EXCEPTION); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializerTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializerTest.java deleted file mode 100644 index c3b6ee4c..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/JsonSerializerTest.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.serialization.serializer.model.User; -import org.junit.Assert; -import org.junit.Test; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Created by liuruisen on 2020/5/27. - */ -public class JsonSerializerTest { - - private JsonSerializer jsonSerializer = new JsonSerializer(); - - @Test - public void serialize() { - User user = new User(); - user.setTags(Arrays.asList("123", "1111")); - user.setUserId(12); - user.setUserName("userName"); - - byte[] bytes = jsonSerializer.serialize(user, User.class); - Assert.assertTrue(bytes.length > 0); - - } - - @Test - public void serializeException() { - User user = null; - // object is null - try { - jsonSerializer.serialize(user, User.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("json-serialize is null")); - } - - // object type is not equals - user = new User(); - try { - jsonSerializer.serialize(user, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("json-serialize is illegal")); - } - - // not support type - try { - jsonSerializer.serialize(new Integer(1), Integer.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("json-serialize is illegal")); - } - } - - @Test - public void deserialize() { - User user = new User(); - user.setTags(Arrays.asList("123", "1111")); - user.setUserId(12); - user.setUserName("userName"); - byte[] bytes = jsonSerializer.serialize(user, User.class); - User user2 = (User) jsonSerializer.deserialize(bytes, User.class); - - Assert.assertTrue(user2.getUserName().equals(user.getUserName())); - Assert.assertTrue(user2.getUserId() == user.getUserId()); - Assert.assertTrue(user2.getTags().equals(user.getTags())); - - // serialize and deserialize String - byte[] stringBytes = jsonSerializer.serialize("Test", String.class); - String result = (String) jsonSerializer.deserialize(stringBytes, String.class); - Assert.assertTrue(result.equals("Test")); - } - - @Test - public void deserializeException() { - - try { - jsonSerializer.deserialize(new byte[0], User.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("empty")); - } - - try { - jsonSerializer.deserialize("123".getBytes(), Integer.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("illegal")); - } - - } - - @Test - public void isSupportTest() { - // map collection - Map map = new HashMap<>(); - map.put("key", "value"); - try { - jsonSerializer.serialize(map, map.getClass()); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("illegal")); - } - - List list = new ArrayList<>(); - list.add("123"); - try { - jsonSerializer.serialize(list, list.getClass()); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("illegal")); - } - - // arr - String[] strings = new String[] {"123", "123"}; - try { - jsonSerializer.serialize(strings, strings.getClass()); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("illegal")); - } - - // primitive - try { - jsonSerializer.serialize(1, int.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - Assert.assertTrue(e.getMessage().contains("illegal")); - } - - } - - @Test - public void deserilizeByType() throws NoSuchMethodException { - User user = new User(); - user.setUserId(123L); - - List users = new ArrayList<>(); - users.add(user); - - byte[] bytes = jsonSerializer.serialize(users, - this.getClass().getMethod("listUsers", List.class).getGenericParameterTypes()[0]); - - List listResult = (List) jsonSerializer.deserialize(bytes, - this.getClass().getMethod("listUsers", List.class).getGenericParameterTypes()[0]); - - assertNotNull(listResult); - assertEquals(1, listResult.size()); - - Map userMap = new HashMap<>(); - userMap.put("test-1", user); - - byte[] bytes2 = jsonSerializer.serialize(userMap, - this.getClass().getMethod("mapUsers", Map.class).getGenericParameterTypes()[0]); - - Map mapResult = (Map) jsonSerializer.deserialize(bytes2, - this.getClass().getMethod("mapUsers", Map.class).getGenericParameterTypes()[0]); - - assertNotNull(mapResult); - assertEquals(1, mapResult.size()); - - TestObj testObj = new TestObj<>(); - testObj.setData(user); - - byte[] bytes3 = jsonSerializer.serialize(testObj, - this.getClass().getMethod("userTestObj", TestObj.class).getGenericParameterTypes()[0]); - - TestObj objResult = (TestObj) jsonSerializer.deserialize(bytes3, - this.getClass().getMethod("userTestObj", TestObj.class).getGenericParameterTypes()[0]); - assertNotNull(objResult); - assertEquals(123L, objResult.data.getUserId()); - } - - public List listUsers(List users) { - return null; - } - - public Map mapUsers(Map users) { - return null; - } - - public TestObj userTestObj(TestObj users) { - return null; - } - - public static class TestObj { - T data; - - public T getData() { - return data; - } - - public void setData(T data) { - this.data = data; - } - } - - @Test - public void testLocalDateTime() { - User user = new User(); - LocalDateTime birthDay = LocalDateTime.now(); - user.setBirthDay(birthDay); - - byte[] data = jsonSerializer.serialize(user, User.class); - Assert.assertNotNull(data); - - User deserializeUser = (User) jsonSerializer.deserialize(data, User.class); - Assert.assertNotNull(deserializeUser); - Assert.assertNotNull(deserializeUser.getBirthDay()); - Assert.assertEquals(deserializeUser.getBirthDay(), birthDay); - } - -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/NewProtostuffSerializeTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/NewProtostuffSerializeTest.java deleted file mode 100644 index a87fefc1..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/NewProtostuffSerializeTest.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.serialization.serializer.model.Address; -import com.baidu.cloud.starlight.serialization.serializer.model.AllNull; -import com.baidu.cloud.starlight.serialization.serializer.model.ExtInfo; -import com.baidu.cloud.starlight.serialization.serializer.model.Sex; -import com.baidu.cloud.starlight.serialization.serializer.model.User; -import com.baidu.cloud.thirdparty.protostuff.LinkedBuffer; -import com.baidu.cloud.thirdparty.protostuff.ProtobufIOUtil; -import com.baidu.cloud.thirdparty.protostuff.Schema; -import com.baidu.cloud.thirdparty.protostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.IdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.RuntimeSchema; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; - -import static org.junit.Assert.assertEquals; - -/** - * Created by liuruisen on 2021/1/19. - */ -public class NewProtostuffSerializeTest { - - protected DefaultIdStrategy newlyStrategy; - - protected DefaultIdStrategy newly3Strategy; - - protected DefaultIdStrategy defaultIdStrategy; - - protected DefaultIdStrategy nullStrategy; - - private User user; - - @Before - public void before() { - defaultIdStrategy = new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS); - - newly3Strategy = - new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS | IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS - | IdStrategy.MORPH_COLLECTION_INTERFACES | IdStrategy.MORPH_MAP_INTERFACES); - - newlyStrategy = new DefaultIdStrategy( - IdStrategy.DEFAULT_FLAGS | IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.MORPH_COLLECTION_INTERFACES - | IdStrategy.MORPH_MAP_INTERFACES | IdStrategy.MORPH_NON_FINAL_POJOS); - - nullStrategy = new DefaultIdStrategy(IdStrategy.DEFAULT_FLAGS | IdStrategy.PRESERVE_NULL_ELEMENTS); - - user = new User(); - user.setUserName("Test-user"); - user.setUserId(123L); - user.setAge(18); - user.setAlive(true); - user.setBalance(11111.333d); - user.setInfo("This is a human"); - user.setSalary(200.67f); - user.setSex(Sex.MALE); - - Address address = new Address("Beijing"); - user.setAddress(address); - List tags = new LinkedList<>(); - tags.add("Key=Value"); - tags.add("Key2=Value2"); - user.setTags(tags); - - TreeSet stringSet = new TreeSet<>(); - stringSet.add("val1"); - stringSet.add("val2"); - user.setSet(stringSet); - - ExtInfo extInfo1 = new ExtInfo("ext1", 123); - ExtInfo extInfo2 = new ExtInfo("ext2", "test"); - LinkedList list = new LinkedList<>(); - list.add(extInfo1); - list.add(extInfo2); - user.setExtInfos(list); - - Object[] arrays = new Object[3]; - arrays[0] = 123; - arrays[1] = address; - arrays[2] = Sex.NONE; - - user.setArray(arrays); - } - - @Test - public void emptyList() { - user.setTags(new LinkedList<>()); - - byte[] bytes3 = serialize(user, User.class, defaultIdStrategy); - User user3 = (User) deserialize(bytes3, User.class, defaultIdStrategy); - System.out.println("defa ser -- defa deser " + user.equals(user3)); - System.out.println(""); - - byte[] bytes4 = serialize(user, User.class, nullStrategy); - User user4 = (User) deserialize(bytes4, User.class, nullStrategy); - System.out.println("null ser -- null deser " + user.equals(user4)); - System.out.println(""); - - byte[] bytes2 = serialize(user, User.class, newly3Strategy); - User user2 = (User) deserialize(bytes2, User.class, newly3Strategy); - System.out.println("newly3 ser -- newly3 deser " + user.equals(user2)); - System.out.println(""); - - byte[] bytes1 = serialize(user, User.class, newlyStrategy); - User user1 = (User) deserialize(bytes1, User.class, newlyStrategy); - System.out.println("newly ser -- newly deser " + user.equals(user1)); - System.out.println(""); - - } - - @Test - public void listMidNull() { - user.setTags(Arrays.asList("1", null, "3")); - - byte[] bytes2 = serialize(user, User.class, newly3Strategy); - User user2 = (User) deserialize(bytes2, User.class, newly3Strategy); - System.out.println("newly3 ser -- newly3 deser " + user.equals(user2)); - System.out.println(""); - - byte[] bytes3 = serialize(user, User.class, defaultIdStrategy); - User user3 = (User) deserialize(bytes3, User.class, defaultIdStrategy); - System.out.println("defa ser -- defa deser " + user.equals(user3)); - System.out.println(""); - - byte[] bytes4 = serialize(user, User.class, nullStrategy); - User user4 = (User) deserialize(bytes4, User.class, nullStrategy); - System.out.println("null ser -- null deser " + user.equals(user4)); - System.out.println(""); - - byte[] bytes1 = serialize(user, User.class, newlyStrategy); - User user1 = (User) deserialize(bytes1, User.class, newlyStrategy); - System.out.println("newly ser -- newly deser " + user.equals(user1)); - System.out.println(""); - } - - @Test - public void subList() { - List stringList = Arrays.asList("1", "2", "3", "4", "5"); - user.setTags(stringList.subList(0, 2)); - - try { - byte[] bytes3 = serialize(user, User.class, defaultIdStrategy); - User user3 = (User) deserialize(bytes3, User.class, defaultIdStrategy); - System.out.println("defal ser -- defal deser " + user.equals(user3)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes4 = serialize(user, User.class, nullStrategy); - User user4 = (User) deserialize(bytes4, User.class, nullStrategy); - System.out.println("null ser -- null deser " + user.equals(user4)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes2 = serialize(user, User.class, newly3Strategy); - User user2 = (User) deserialize(bytes2, User.class, newly3Strategy); - System.out.println("new3 ser -- new3 deser " + user.equals(user2)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes1 = serialize(user, User.class, newlyStrategy); - User user1 = (User) deserialize(bytes1, User.class, newlyStrategy); - System.out.println("new ser -- new deser " + user.equals(user1)); - } catch (CodecException e) { - e.printStackTrace(); - } - } - - @Test - public void allNull() { - - ExtInfo extInfo = new ExtInfo(); - byte[] bytes = serialize(extInfo, ExtInfo.class, nullStrategy); - - System.out.println(Arrays.toString(bytes)); - - ExtInfo extInfo1 = (ExtInfo) deserialize(bytes, ExtInfo.class, nullStrategy); - System.out.println(extInfo1); - - ExtInfo extInfo2 = new ExtInfo(); - byte[] bytes2 = serialize(extInfo2, ExtInfo.class, defaultIdStrategy); - System.out.println(Arrays.toString(bytes2)); - - ExtInfo extInfo3 = (ExtInfo) deserialize(bytes2, ExtInfo.class, defaultIdStrategy); - System.out.println(extInfo3); - - AllNull allNull = new AllNull(); - byte[] bytes3 = serialize(allNull, AllNull.class, nullStrategy); - - System.out.println(Arrays.toString(bytes3)); - - AllNull allNull2 = (AllNull) deserialize(bytes3, AllNull.class, nullStrategy); - System.out.println(allNull2); - - AllNull allNull3 = new AllNull(); - byte[] bytes4 = serialize(allNull3, AllNull.class, defaultIdStrategy); - System.out.println(Arrays.toString(bytes4)); - - AllNull allNull5 = (AllNull) deserialize(bytes4, AllNull.class, defaultIdStrategy); - System.out.println(allNull5); - - List extInfos = new ArrayList<>(); - extInfos.add(new ExtInfo("Key1", "Value1")); - extInfos.add(new ExtInfo("Key2", "Value2")); - - byte[] listNullBytes = serialize(extInfos, extInfos.getClass(), newly3Strategy); - System.out.println(Arrays.toString(listNullBytes)); - - try { - List extInfos2 = (List) deserialize(listNullBytes, List.class, newly3Strategy); - System.out.println(extInfos2); - } catch (CodecException e) { - assertEquals(CodecException.DESERIALIZE_EXCEPTION, e.getCode()); - } - } - - @Test - public void keySet() { - Map map = new HashMap<>(); - map.put("1", "1"); - map.put("2", "2"); - map.put("3", "3"); - TreeSet sets = new TreeSet(); - sets.addAll(map.keySet()); - user.setSet(sets); - - try { - byte[] bytes3 = serialize(user, User.class, defaultIdStrategy); - User user3 = (User) deserialize(bytes3, User.class, defaultIdStrategy); - System.out.println("defal ser -- defal deser " + user.equals(user3)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes4 = serialize(user, User.class, nullStrategy); - User user4 = (User) deserialize(bytes4, User.class, nullStrategy); - System.out.println("null ser -- null deser " + user.equals(user4)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes2 = serialize(user, User.class, newly3Strategy); - User user2 = (User) deserialize(bytes2, User.class, newly3Strategy); - System.out.println("new3 ser -- new3 deser " + user.equals(user2)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes1 = serialize(user, User.class, newlyStrategy); - User user1 = (User) deserialize(bytes1, User.class, newlyStrategy); - System.out.println("new ser -- new deser " + user.equals(user1)); - } catch (CodecException e) { - e.printStackTrace(); - } - } - - @Test - public void emptyMap() { - - user.setMap(Collections.emptyMap()); - - try { - byte[] bytes3 = serialize(user, User.class, defaultIdStrategy); - User user3 = (User) deserialize(bytes3, User.class, defaultIdStrategy); - System.out.println("defal ser -- defal deser " + user.equals(user3)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes4 = serialize(user, User.class, nullStrategy); - User user4 = (User) deserialize(bytes4, User.class, nullStrategy); - System.out.println("null ser -- null deser " + user.equals(user4)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes2 = serialize(user, User.class, newly3Strategy); - User user2 = (User) deserialize(bytes2, User.class, newly3Strategy); - System.out.println("new3 ser -- new3 deser " + user.equals(user2)); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - byte[] bytes1 = serialize(user, User.class, newlyStrategy); - User user1 = (User) deserialize(bytes1, User.class, newlyStrategy); - System.out.println("new ser -- new deser " + user.equals(user1)); - } catch (CodecException e) { - e.printStackTrace(); - } - } - - @Test - public void test() { - - byte[] bytes = serialize(user, User.class, defaultIdStrategy); - - byte[] bytes2 = serialize(user, User.class, nullStrategy); - - try { - User user1 = (User) deserialize(bytes, User.class, nullStrategy); - System.out.println(user1); - } catch (CodecException e) { - e.printStackTrace(); - } - - try { - User user2 = (User) deserialize(bytes2, User.class, defaultIdStrategy); - System.out.println(user2); - } catch (CodecException e) { - e.printStackTrace(); - } - } - - private static final int DEFAULT_ALLOCATE_NUM = 512; - // Re-use (manage) this buffer to avoid allocating on every serialization - private ThreadLocal buffer = new ThreadLocal() { - @Override - protected LinkedBuffer initialValue() { - return LinkedBuffer.allocate(DEFAULT_ALLOCATE_NUM); - } - }; - - protected Object deserialize(byte[] bytes, Class type, IdStrategy idStrategy) throws CodecException { - - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(type, idStrategy); // schema will be cached - Object content = schema.newMessage(); - ProtobufIOUtil.mergeFrom(bytes, content, schema); - return content; - } catch (Exception e) { - throw new CodecException(CodecException.DESERIALIZE_EXCEPTION, - "Protostuff Deserialize error: " + e.getMessage(), e); - } - } - - protected byte[] serialize(Object obj, Class type, IdStrategy idStrategy) throws CodecException { - - // use predefine object container as default - try { - Schema schema = RuntimeSchema.getSchema(type, idStrategy); // schema will be cached - return ProtobufIOUtil.toByteArray(obj, schema, buffer.get()); - } catch (Exception e) { - throw new CodecException(CodecException.SERIALIZE_EXCEPTION, - "Protostuff serialize error: " + e.getMessage(), e); - } finally { - buffer.get().clear(); - } - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializerTest.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializerTest.java deleted file mode 100644 index 478b0915..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/ProtoStuffSerializerTest.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer; - -import com.baidu.cloud.thirdparty.protostuff.runtime.DefaultIdStrategy; -import com.baidu.cloud.thirdparty.protostuff.runtime.IdStrategy; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.Wrapper; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Created by liuruisen on 2020/3/19. - */ -public class ProtoStuffSerializerTest { - - private ProtoStuffSerializer serializer = new ProtoStuffSerializer(); - - private static final int idStrategyFlag = 0 | IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES; - - @Test - public void serialize() { - byte[] bytes1 = serializer.serialize("Test", String.class); - String str = (String) serializer.deserialize(bytes1, String.class); - Assert.assertTrue(str.equals("Test")); - } - - @Test - public void serializeIdStrategy() { - byte[] bytes2 = serializer.serialize("Test", String.class, idStrategyFlag); - String str2 = (String) serializer.deserialize(bytes2, String.class); - Assert.assertTrue(str2.equals("Test")); - } - - @Test - public void serializeException() { - try { - // message null - serializer.serialize(null, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // type null - serializer.serialize("123", null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // not support single long int boolean - serializer.serialize(1l, long.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // serialize exception - serializer.serialize(1, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - } - - @Test - public void serializeIdStrategyException() { - try { - // message null - serializer.serialize(null, String.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // type null - serializer.serialize("123", null, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // not support single long int boolean - serializer.serialize(1L, long.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - - try { - // serialize exception - serializer.serialize(1, String.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.SERIALIZE_EXCEPTION)); - } - } - - @Test - public void deserializeException() { - - try { - // bytes null - serializer.deserialize(null, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // bytes length 0 - serializer.deserialize(new byte[0], String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - byte[] bytes1 = serializer.serialize(1, Integer.class); - try { - // type null - serializer.deserialize(bytes1, null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // type isPrimitive - serializer.deserialize(bytes1, int.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // deserialize exception - serializer.deserialize(bytes1, String.class); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - } - - @Test - public void deserializeIdStrategyException() { - IdStrategy strategy = new DefaultIdStrategy(); - - try { - // bytes null - serializer.deserialize(null, String.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // bytes length 0 - serializer.deserialize(new byte[0], String.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - byte[] bytes1 = serializer.serialize(1, Integer.class, idStrategyFlag); - try { - // type null - serializer.deserialize(bytes1, null); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // type isPrimitive - serializer.deserialize(bytes1, int.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - - try { - // deserialize exception - serializer.deserialize(bytes1, String.class, idStrategyFlag); - } catch (CodecException e) { - Assert.assertTrue(e.getCode().equals(CodecException.DESERIALIZE_EXCEPTION)); - } - } - - @Test - public void wrapperSerialize() { - Map map = new HashMap<>(); - map.put("Key", "Value"); - Object[] args = new Object[] {"MethodName", new Object[] {"hello", map}}; - Wrapper wrapper = new Wrapper(args); - - byte[] bytes = serializer.serialize(wrapper, Wrapper.class); - - Wrapper params = (Wrapper) serializer.deserialize(bytes, Wrapper.class); - - Object[] objects = (Object[]) params.getObj(); - Assert.assertEquals(objects[0], "MethodName"); - Object[] objects1 = (Object[]) objects[1]; - Assert.assertEquals(objects1[0], "hello"); - Assert.assertEquals(((Map) objects1[1]).get("Key"), "Value"); - } - - @Test - public void exceptionConvert() { - - ProtoStuffSerializer serializer = new ProtoStuffSerializer(); - - AsListModel model = new AsListModel(); - List strList = new ArrayList<>(); - strList.add("45600"); - model.setAsList(strList); - - byte[] bytes = serializer.serialize(model, AsListModel.class); - - try { - serializer.deserialize(bytes, AsListModel.class, 4); - } catch (CodecException e) { - Assert.assertEquals(CodecException.DESERIALIZE_EXCEPTION, e.getCode()); - System.out.println(e); - } - - WrapModel wrapModel = new WrapModel(); - wrapModel.setAsListModel(model); - - byte[] bytes2 = serializer.serialize(wrapModel, WrapModel.class, 6); - - try { - serializer.deserialize(bytes2, WrapModel.class, 6); - } catch (CodecException e) { - Assert.assertEquals(CodecException.DESERIALIZE_EXCEPTION, e.getCode()); - System.out.println(e); - } - - } - - private class WrapModel { - private AsListModel asListModel; - - public AsListModel getAsListModel() { - return asListModel; - } - - public void setAsListModel(AsListModel asListModel) { - this.asListModel = asListModel; - } - } - - private class AsListModel { - List asList = Arrays.asList("123"); - - public List getAsList() { - return asList; - } - - public void setAsList(List asList) { - this.asList = asList; - } - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Address.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Address.java deleted file mode 100644 index a04d1d82..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Address.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.Objects; - -public class Address { - private String address; - - public Address(String address) { - this.address = address; - } - - public Address() {} - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("Address{"); - sb.append("address='").append(address).append('\''); - sb.append('}'); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Address address1 = (Address) o; - return Objects.equals(address, address1.address); - } - - @Override - public int hashCode() { - return Objects.hash(address); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/AllNull.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/AllNull.java deleted file mode 100644 index 01ad0b0c..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/AllNull.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.List; - -/** - * Created by liuruisen on 2021/2/3. - */ -public class AllNull { - - List ids; - - Boolean isTrue; - - String strInfo; - - String strInfo2; - - public List getIds() { - return ids; - } - - public void setIds(List ids) { - this.ids = ids; - } - - public Boolean getTrue() { - return isTrue; - } - - public void setTrue(Boolean aTrue) { - isTrue = aTrue; - } - - public String getStrInfo() { - return strInfo; - } - - public void setStrInfo(String strInfo) { - this.strInfo = strInfo; - } - - public String getStrInfo2() { - return strInfo2; - } - - public void setStrInfo2(String strInfo2) { - this.strInfo2 = strInfo2; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("AllNull{"); - sb.append("ids=").append(ids); - sb.append(", isTrue=").append(isTrue); - sb.append(", strInfo='").append(strInfo).append('\''); - sb.append(", strInfo2='").append(strInfo2).append('\''); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseDto.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseDto.java deleted file mode 100644 index a0f35534..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseDto.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -public class BaseDto { - - private Long appId; - private String appToken; - - public BaseDto(Long appId, String appToken) { - this.appId = appId; - this.appToken = appToken; - } - - public Long getAppId() { - return appId; - } - - public void setAppId(Long appId) { - this.appId = appId; - } - - public String getAppToken() { - return appToken; - } - - public void setAppToken(String appToken) { - this.appToken = appToken; - } - -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BasePageRequestDto.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BasePageRequestDto.java deleted file mode 100644 index a59d0be0..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BasePageRequestDto.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.List; - -public class BasePageRequestDto extends BaseDto { - - private int pageSize; - private int pageNo; - private List orderBys; - - public BasePageRequestDto(Long appId, String appToken) { - super(appId, appToken); - } - - public int getPageSize() { - return pageSize; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public int getPageNo() { - return pageNo; - } - - public void setPageNo(int pageNo) { - this.pageNo = pageNo; - } - - public List getOrderBys() { - return orderBys; - } - - public void setOrderBys(List orderBys) { - this.orderBys = orderBys; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("BasePageRequestDto{"); - sb.append("pageSize=").append(pageSize); - sb.append(", pageNo=").append(pageNo); - sb.append(", orderBys=").append(orderBys); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseResponse.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseResponse.java deleted file mode 100644 index 8cf6058a..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/BaseResponse.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -/** - * Created by liuruisen on 2021/2/4. - */ -public class BaseResponse { - - public static class LegoReturnCode { - public static final int MAX_CODE = 100; - public static final int SUCCESS = 0; - public static final int INVALID_PARAMETER = 1; - public static final int UNKNOWN_FAILURE = 2; - public static final int NO_AUTHORITY = 3; - public static final int TEMPLATE_NOT_RELEASED = 4; - public static final int DEPENDENT_MODULE_FAILURE = 5; - public static final int UPLOAD_FILE_FAILURE = 6; - public static final int VALIDATE_FAILURE = 7; - public static final int PARTIAL_SUCCESS = 8; - public static final int TEMPLATE_JS_ERROR = 9; - public static final int NO_NEW_TEMPLATE_VERSION = 10; - - public static final String[] RETRUN_MSG = new String[MAX_CODE]; - static { - RETRUN_MSG[SUCCESS] = "success"; - RETRUN_MSG[INVALID_PARAMETER] = "invalid parameter"; - RETRUN_MSG[UNKNOWN_FAILURE] = "unknown failure"; - RETRUN_MSG[NO_AUTHORITY] = "no authority"; - RETRUN_MSG[TEMPLATE_NOT_RELEASED] = "template not released"; - RETRUN_MSG[DEPENDENT_MODULE_FAILURE] = "lego's dependent module failure"; - RETRUN_MSG[UPLOAD_FILE_FAILURE] = "upload file failure"; - RETRUN_MSG[VALIDATE_FAILURE] = "vaildate failure"; - RETRUN_MSG[PARTIAL_SUCCESS] = "partial success"; - RETRUN_MSG[TEMPLATE_JS_ERROR] = "template js error"; - RETRUN_MSG[NO_NEW_TEMPLATE_VERSION] = "can not convert material without new version"; - } - } - - private int returnCode; - private String returnMessage; - - public int getReturnCode() { - return returnCode; - } - - public void setReturnCode(int returnCode) { - this.returnCode = returnCode; - } - - public String getReturnMessage() { - return returnMessage; - } - - public void setReturnMessage(String returnMessage) { - this.returnMessage = returnMessage; - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/ExtInfo.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/ExtInfo.java deleted file mode 100644 index 24a20651..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/ExtInfo.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.Objects; - -public class ExtInfo { - private String key; - - private Object value; - - public ExtInfo() { - - } - - public ExtInfo(String key, Object value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("ExtInfo{"); - sb.append("key='").append(key).append('\''); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - ExtInfo extInfo = (ExtInfo) o; - return Objects.equals(key, extInfo.key) && Objects.equals(value, extInfo.value); - } - - @Override - public int hashCode() { - return Objects.hash(key, value); - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/OrderBy.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/OrderBy.java deleted file mode 100644 index 8cfc77a3..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/OrderBy.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.Objects; - -public class OrderBy { - public enum OrderType { - ASC, DESC - } - - private String property; - - private OrderType orderType; - - public OrderBy(final String property, final OrderType orderType) { - - this.property = property; - this.orderType = orderType; - } - - public String property() { - return property; - } - - public OrderType orderType() { - return orderType; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - OrderBy orderBy = (OrderBy) o; - return Objects.equals(property, orderBy.property) && orderType == orderBy.orderType; - } - - @Override - public int hashCode() { - return Objects.hash(property, orderType); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("OrderBy{"); - sb.append("property='").append(property).append('\''); - sb.append(", orderType=").append(orderType); - sb.append('}'); - return sb.toString(); - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/PageResponse.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/PageResponse.java deleted file mode 100644 index 6cf8a649..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/PageResponse.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.util.List; - -/** - * Created by liuruisen on 2021/2/4. - */ -public class PageResponse extends BaseResponse { - - private int pageNo; - private int pageSize; - private int totalCount; - private List list; - private List orderBys; - - public int getPageNo() { - return pageNo; - } - - public void setPageNo(int pageNo) { - this.pageNo = pageNo; - } - - public int getPageSize() { - return pageSize; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public int getTotalCount() { - return totalCount; - } - - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } - - public List getList() { - return list; - } - - public void setList(List list) { - this.list = list; - } - - public List getOrderBys() { - return orderBys; - } - - public void setOrderBys(List orderBys) { - this.orderBys = orderBys; - } -} diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Sex.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Sex.java deleted file mode 100644 index 32cf94d4..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/Sex.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -public enum Sex { - MALE("male"), FEMALE("female"), NONE("none"); - - private final String name; - - Sex(String name) { - this.name = name; - } -} \ No newline at end of file diff --git a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/User.java b/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/User.java deleted file mode 100644 index 842c3177..00000000 --- a/starlight/starlight-serialization/src/test/java/com/baidu/cloud/starlight/serialization/serializer/model/User.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.serialization.serializer.model; - -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; - -/** - * Created by liuruisen on 2020/5/28. - */ -public class User { - - private long userId; - - private Sex sex; - - private int age; - - private String userName; - - private double balance; - - private float salary; - - private Address address; - - private List tags; - - private LinkedList extInfos; // proto2 not support map, please transform to list - - private boolean alive; - - private String info; - - private TreeSet set; - - private Object[] array; - - private Map map; - - private LocalDateTime birthDay; - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public LinkedList getExtInfos() { - return extInfos; - } - - public void setExtInfos(LinkedList extInfos) { - this.extInfos = extInfos; - } - - public Sex getSex() { - return sex; - } - - public void setSex(Sex sex) { - this.sex = sex; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public float getSalary() { - return salary; - } - - public void setSalary(float salary) { - this.salary = salary; - } - - public Address getAddress() { - return address; - } - - public void setAddress(Address address) { - this.address = address; - } - - public boolean isAlive() { - return alive; - } - - public void setAlive(boolean alive) { - this.alive = alive; - } - - public String getInfo() { - return info; - } - - public void setInfo(String info) { - this.info = info; - } - - public TreeSet getSet() { - return set; - } - - public void setSet(TreeSet set) { - this.set = set; - } - - public Object[] getArray() { - return array; - } - - public void setArray(Object[] array) { - this.array = array; - } - - public Map getMap() { - return map; - } - - public void setMap(Map map) { - this.map = map; - } - - public LocalDateTime getBirthDay() { - return birthDay; - } - - public void setBirthDay(LocalDateTime birthDay) { - this.birthDay = birthDay; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("User{"); - sb.append("userId=").append(userId); - sb.append(", sex=").append(sex); - sb.append(", age=").append(age); - sb.append(", userName='").append(userName).append('\''); - sb.append(", balance=").append(balance); - sb.append(", salary=").append(salary); - sb.append(", address=").append(address); - sb.append(", tags=").append(tags); - sb.append(", extInfos=").append(extInfos); - sb.append(", alive=").append(alive); - sb.append(", info='").append(info).append('\''); - sb.append(", set=").append(set); - sb.append(", array=").append(Arrays.toString(array)); - sb.append(", map=").append(map); - sb.append('}'); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - User user = (User) o; - return userId == user.userId && age == user.age && Double.compare(user.balance, balance) == 0 - && Float.compare(user.salary, salary) == 0 && alive == user.alive && sex == user.sex - && Objects.equals(userName, user.userName) && Objects.equals(address, user.address) - && Objects.equals(tags, user.tags) && Objects.equals(extInfos, user.extInfos) - && Objects.equals(info, user.info) && Objects.equals(set, user.set) && Arrays.equals(array, user.array) - && Objects.equals(map, user.map); - } - - @Override - public int hashCode() { - int result = - Objects.hash(userId, sex, age, userName, balance, salary, address, tags, extInfos, alive, info, set, map); - result = 31 * result + Arrays.hashCode(array); - return result; - } -} diff --git a/starlight/starlight-transport/pom.xml b/starlight/starlight-transport/pom.xml deleted file mode 100644 index ddedb168..00000000 --- a/starlight/starlight-transport/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - - com.baidu.cloud - starlight - 2025.0.1-SNAPSHOT - - - starlight-transport - - true - - - - com.baidu.cloud - starlight-protocol-brpc - ${project.version} - - - - com.baidu.cloud - starlight-protocol-stargate - ${project.version} - - - - com.baidu.cloud - starlight-protocol-http - ${project.version} - - - - org.powermock - powermock-module-junit4 - test - - - - org.powermock - powermock-api-mockito2 - test - - - - diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/StarlightTransportFactory.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/StarlightTransportFactory.java deleted file mode 100644 index cf4cc1e2..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/StarlightTransportFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.api.transport.TransportFactory; -import com.baidu.cloud.starlight.transport.netty.NettyClient; -import com.baidu.cloud.starlight.transport.netty.NettyServer; - -/** - * Default TransportFactory, produce {@link NettyClient} SPI name: starlight Created by liuruisen on 2020/2/3. - */ -public class StarlightTransportFactory implements TransportFactory { - - @Override - public ClientPeer client(URI uri) { - return new NettyClient(uri); - } - - @Override - public ServerPeer server(URI uri) { - return new NettyServer(uri); - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactory.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactory.java deleted file mode 100644 index f409e13b..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.pool2.BasePooledObjectFactory; -import com.baidu.cloud.thirdparty.pool2.PooledObject; -import com.baidu.cloud.thirdparty.pool2.impl.DefaultPooledObject; - -/** - * Channel pool factory used in rpc client to produce Channel Created by liuruisen on 2020/3/31. - */ -public class ChannelPooledObjectFactory extends BasePooledObjectFactory { - - private final NettyRpcChannelGroup rpcChannelGroup; - - public ChannelPooledObjectFactory(NettyRpcChannelGroup rpcChannelGroup) { - this.rpcChannelGroup = rpcChannelGroup; - } - - @Override - public RpcChannel create() throws Exception { - return new LongRpcChannel(rpcChannelGroup.connect(), ChannelSide.CLIENT, rpcChannelGroup); - } - - @Override - public PooledObject wrap(RpcChannel obj) { - return new DefaultPooledObject<>(obj); - } - - @Override - public void destroyObject(PooledObject p) throws Exception { - RpcChannel channel = p.getObject(); - new Thread(channel::close).start(); - } - - /** - * Ensure the RpcChannel is safe to be retured by the pool - * - * @param p - * @return - */ - @Override - public boolean validateObject(PooledObject p) { - RpcChannel channel = p.getObject(); - return channel.isActive(); - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannel.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannel.java deleted file mode 100644 index dddc628b..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannel.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.rpc.callback.Callback; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannelGroup; -import com.baidu.cloud.starlight.protocol.http.springrest.SpringRestProtocol; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFutureListener; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderValues; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetSocketAddress; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Long Single Channel Created by liuruisen on 2020/2/3. - */ -public class LongRpcChannel implements RpcChannel { - - protected static final Logger LOGGER = LoggerFactory.getLogger(NettyRpcChannelGroup.class); - - private final Map callbacks; - - private final Map attributes; - - private volatile Channel channel; - - private final ChannelSide side; - - private RpcChannelGroup channelGroup; - - private AtomicBoolean inited = new AtomicBoolean(false); - - public LongRpcChannel(Channel channel, ChannelSide side) { - this(channel, side, null); - } - - public LongRpcChannel(Channel channel, ChannelSide side, RpcChannelGroup channelGroup) { - this.callbacks = new ConcurrentHashMap<>(); - this.attributes = new ConcurrentHashMap<>(); - this.channel = channel; - this.side = side; - this.channelGroup = channelGroup; - init(); - } - - @Override - public void init() { - if (!inited.compareAndSet(false, true)) { - return; - } - - ChannelAttribute attribute = new ChannelAttribute(this); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelSide side() { - return side; - } - - @Override - public InetSocketAddress getRemoteAddress() { - if (channel == null) { - return null; - } - return (InetSocketAddress) channel.remoteAddress(); - } - - @Override - public InetSocketAddress getLocalAddress() { - if (channel == null) { - return null; - } - return (InetSocketAddress) channel.localAddress(); - } - - @Override - public boolean isActive() { - return channel != null && channel.isActive() && inited.get(); - } - - @Override - public void reconnect() throws TransportException { - if (getRpcChannelGroup() != null) { - getRpcChannelGroup().removeRpcChannel(this); // remove and reconnect - } - } - - @Override - public void send(MsgBase msgBase) throws TransportException { - if (!isActive()) { - throw new TransportException(TransportException.WRITE_EXCEPTION, "Channel is inactive, " + "remoteHost: " - + getRemoteAddress().getAddress() + ", remotePort: " + getRemoteAddress().getPort()); - } - // write and flush message - ChannelFuture sendFuture = channel.writeAndFlush(msgBase); - sendFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if (!channelFuture.isSuccess()) { - String causeByMsg = - channelFuture.cause() == null ? "netty exception" : channelFuture.cause().getMessage(); - String errorMsg = String.format("Fail to send message to remote, url[%s:%s], error message: %s", - getRemoteAddress().getAddress(), getRemoteAddress().getPort(), causeByMsg); - if (side().equals(ChannelSide.CLIENT)) { - Callback callback = removeCallback(msgBase.getId()); - if (callback != null) { - callback.onError(new TransportException(TransportException.WRITE_EXCEPTION, errorMsg)); - } - } - LOGGER.warn(errorMsg); - } - - // http protocol and short connection: Connection:close - // fixme 关闭连接放在了send之后,是不是不太合理? - if (side().equals(ChannelSide.SERVER) - && msgBase.getProtocolName().equalsIgnoreCase(SpringRestProtocol.PROTOCOL_NAME) - && isHttpShortConnection(msgBase)) { - channelFuture.channel().close(); - } - } - }); - } - - @Override - public void receive(MsgBase msgBase) { - // FIXME find reasonable use: do some biz operations such as metrics - // LOGGER.debug("Receive Message from remote peer, RequestId: " + msgBase.getId()); - } - - @Override - public void putCallback(long id, RpcCallback callback) { - if (side().equals(ChannelSide.SERVER)) { - throw new StarlightRpcException( - "RpcChannel side is SERVER, not support putCallback. " + "RequestId: " + id); - } - callbacks.putIfAbsent(id, callback); - } - - @Override - public RpcCallback removeCallback(long id) { - if (side().equals(ChannelSide.SERVER)) { - throw new StarlightRpcException( - "RpcChannel side is SERVER, not support removeCallback. " + "RequestId: " + id); - } - return callbacks.remove(id); - } - - @Override - public void close() { - if (!inited.getAndSet(false)) { // not inited - return; - } - - // clear callback - if (callbacks.size() > 0) { - LOGGER.warn( - "There are still unfinished requests when RpcChannel close, size {}, channelId {}, " - + "remoteAddress {}, will wait and handle this requests.", - callbacks.size(), channel.id().asLongText(), channel.remoteAddress()); - clearCallbacks(); - } - - // remove old channel related classloader from LocalContext - LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY).set(channel.id().asLongText(), null); - - if (channel != null) { - LOGGER.info("The netty channel is closing, channel {}, remoteAddress {}", channel.id().asLongText(), - channel.remoteAddress()); - channel.close(); - } - } - - @Override - public void setAttribute(String attributeKey, Object attributeVal) { - attributes.put(attributeKey, attributeVal); - } - - @Override - public Object getAttribute(String attributeKey) { - return attributes.get(attributeKey); - } - - @Override - public Object removeAttribute(String attributeKey) { - return attributes.remove(attributeKey); - } - - private boolean isHttpShortConnection(MsgBase msgBase) { - if (msgBase == null) { - return false; - } - - if (!(msgBase instanceof Response)) { - return false; - } - - Response response = (Response) msgBase; - if (response.getRequest().getAttachmentKv() == null || response.getRequest().getAttachmentKv().size() == 0) { - return false; - } - - Object connection = response.getRequest().getAttachmentKv().get(HttpHeaderNames.CONNECTION.toString()); - if (!(connection instanceof String)) { - return false; - } - - return ((String) connection).equalsIgnoreCase(HttpHeaderValues.CLOSE.toString()); - } - - @Override - public String toString() { - return channel.id().asLongText(); - } - - @Override - public RpcChannelGroup getRpcChannelGroup() { - return this.channelGroup; - } - - @Override - public Map allCallbacks() { - return this.callbacks; - } - - /** - * Will be called when close channel, to prevent unhandled callback - */ - protected void clearCallbacks() { - long startClearTime = System.currentTimeMillis(); - - for (;;) { - if (callbacks.size() <= 0) { - LOGGER.info("The channel has handled all request, will close, channelId {}, remoteAddr {}", - channel.id().asLongText(), channel.remoteAddress()); - break; - } - - // FIXME 兜底方案,实际场景会走不到,因为每个请求对应的callback均有超时时间 - if ((System.currentTimeMillis() - startClearTime) > (1000 * 60 * 3)) { // max wait 3 min - LOGGER.error("The request has not been processed after waiting 3 minutes when closing channel. " - + "Unhandled request size {}, will response timeout", callbacks.size()); - for (RpcCallback callback : callbacks.values()) { - callback.onError(StarlightRpcException.timeoutException(callback.getRequest(), - getRemoteAddress().getAddress().getHostAddress() + ":" + getRemoteAddress().getPort())); - } - callbacks.clear(); - - break; - } - - try { - TimeUnit.SECONDS.sleep(10); - } catch (InterruptedException e) { - LOGGER.error( - "Thread interrupted when clearCallbacks, remind callback size {}, " + "will response timeout", - callbacks.size()); - // ignore - } - } - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/NettyRpcChannelGroup.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/NettyRpcChannelGroup.java deleted file mode 100644 index b5300daf..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/NettyRpcChannelGroup.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannelGroup; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetSocketAddress; - -/** - * Created by liuruisen on 2020/2/4. - */ -public abstract class NettyRpcChannelGroup implements RpcChannelGroup { - - protected static final Logger LOGGER = LoggerFactory.getLogger(NettyRpcChannelGroup.class); - - private URI uri; - - private final Bootstrap bootstrap; - - public NettyRpcChannelGroup(URI uri, Bootstrap bootstrap) { - this.uri = uri; - this.bootstrap = bootstrap; - } - - @Override - public URI getUri() { - return this.uri; - } - - /** - * Connect to the remote server, and return a netty {@link Channel} - * - * @return - * @throws TransportException - */ - public synchronized Channel connect() throws TransportException { - ChannelFuture channelFuture = null; - try { - channelFuture = bootstrap.connect(getConnectAddress()); - int connectTimeout = uri.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.CONNECT_TIMEOUT_VALUE); - channelFuture.awaitUninterruptibly(connectTimeout); // wait until connect complete, so we can return Channel - if (channelFuture.isSuccess()) { - Channel result = channelFuture.channel(); - LOGGER.info("Create new channel {}, remoteAddress {}", result.id().asLongText(), - result.remoteAddress()); - return result; - } else { - String causeByMsg = - channelFuture.cause() == null ? "Connect timeout" : channelFuture.cause().getMessage(); - LOGGER.info("Create new channel failed, remoteAddress {}, cause by {}", getConnectAddress(), - causeByMsg); - throw new TransportException(TransportException.CONNECT_EXCEPTION, "Connect to url:" - + getUri().getHost() + ":" + getUri().getPort() + " failed, " + " cause by : " + causeByMsg); - } - } catch (Exception e) { - if (e instanceof TransportException) { - throw e; - } - if (channelFuture != null /*&& !channelFuture.isSuccess()*/) { - /*// clean abnormal channel to prevent some unexpected error - disconnect(channelFuture.channel());*/ - String causeByMsg = - channelFuture.cause() == null ? "Connect timeout" : channelFuture.cause().getMessage(); - LOGGER.info("Create new channel failed, remoteAddress {}, cause by {}", getConnectAddress(), - causeByMsg); - throw new TransportException(TransportException.CONNECT_EXCEPTION, "Connect to url:" - + getUri().getHost() + ":" + getUri().getPort() + " failed, " + " cause by : " + causeByMsg); - } - throw new TransportException(TransportException.CONNECT_EXCEPTION, e.getMessage(), e); - } - } - - protected InetSocketAddress getConnectAddress() { - return new InetSocketAddress(getUri().getHost(), getUri().getPort()); - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/PooledRpcChannelGroup.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/PooledRpcChannelGroup.java deleted file mode 100644 index 5149b67f..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/PooledRpcChannelGroup.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.pool2.PooledObject; -import com.baidu.cloud.thirdparty.pool2.impl.DefaultPooledObjectInfo; -import com.baidu.cloud.thirdparty.pool2.impl.GenericObjectPool; -import com.baidu.cloud.thirdparty.pool2.impl.GenericObjectPoolConfig; - -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; - -/** - * PooledRpcChannel: keep fixed connections with one server Created by liuruisen on 2020/3/31. - */ -public class PooledRpcChannelGroup extends NettyRpcChannelGroup { - - private GenericObjectPool channelPool; - - public PooledRpcChannelGroup(URI uri, Bootstrap bootstrap) { - super(uri, bootstrap); - // init(); - } - - @Override - public RpcChannel getRpcChannel() { - try { - RpcChannel rpcChannel = channelPool.borrowObject(); - LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY) - .set(rpcChannel.channel().id().asLongText(), Thread.currentThread().getContextClassLoader()); - return rpcChannel; - } catch (Exception e) { - throw new TransportException(TransportException.CONNECT_EXCEPTION, - "Get Channel from pool failed :" + e.getMessage()); - } - } - - /** - * Return channel to channelPool - * - * @param rpcChannel - */ - @Override - public void returnRpcChannel(RpcChannel rpcChannel) { - try { - channelPool.returnObject(rpcChannel); - } catch (Exception e) { - LOGGER.debug("Return channel failed:{} to PooledChannel", e.getMessage()); - } - } - - /** - * PooledChannel reconnect means invalidate channel and create new by GenericObjectPool - * - * @param rpcChannel - */ - @Override - public void removeRpcChannel(RpcChannel rpcChannel) { - try { - channelPool.invalidateObject(rpcChannel); - } catch (Exception e) { - LOGGER.debug("Remove channel failed from PooledChannelGroup.", e); - } - } - - @Override - public int rpcChannelCount() { - return channelPool.listAllObjects().size(); - } - - /** - * PooledChannel init means prepare ChannelPool - */ - @Override - public void init() { - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); - poolConfig - .setMaxWaitMillis(getUri().getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.CONNECT_TIMEOUT_VALUE)); - poolConfig - .setMaxTotal(getUri().getParameter(Constants.MAX_TOTAL_CONNECTIONS_KEY, Constants.MAX_TOTAL_CONNECTIONS)); - poolConfig - .setMaxIdle(getUri().getParameter(Constants.MAX_IDLE_CONNECTIONS_KEY, Constants.MAX_IDLE_CONNECTIONS)); - poolConfig - .setMinIdle(getUri().getParameter(Constants.MIN_IDLE_CONNECTIONS_KEY, Constants.MIN_IDLE_CONNECTIONS)); - // Connect test when idle, start asynchronous evict thread for failure detection - poolConfig.setTestWhileIdle(true); - poolConfig.setTestOnBorrow(true); - poolConfig.setTimeBetweenEvictionRunsMillis(Constants.TIME_BETWEEN_EVICTION_RUN_MILLS); - - channelPool = new GenericObjectPool<>(new ChannelPooledObjectFactory(this), poolConfig); - - try { - channelPool.preparePool(); - } catch (Exception e) { - LOGGER.warn("Init min idle object pool failed"); - } - } - - @Override - public void close() { - channelPool.close(); - } - - @Override - public Set allRpcChannels() { - Set rpcChannels = new HashSet<>(); - Set pooledObjectInfos = channelPool.listAllObjects(); - try { - for (DefaultPooledObjectInfo pooledObjectInfo : pooledObjectInfos) { - Field pooledObjectField = pooledObjectInfo.getClass().getDeclaredField("pooledObject"); - pooledObjectField.setAccessible(true); - PooledObject pooledObject = (PooledObject) pooledObjectField.get(pooledObjectInfo); - rpcChannels.add((RpcChannel) pooledObject.getObject()); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - LOGGER.error("Get all rpcChannels from PooledChannelGroup failed", e); - } - - return rpcChannels; - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroup.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroup.java deleted file mode 100644 index a06962d5..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroup.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Single long RpcChannel group. Created by liuruisen on 2020/11/25. - */ -public class SingleRpcChannelGroup extends NettyRpcChannelGroup { - - private static final Integer CHANNEL_NUM = 1; - - private RpcChannel rpcChannel; - - private AtomicBoolean inited = new AtomicBoolean(false); - - private Set reconnectTimeouts; - - public SingleRpcChannelGroup(URI uri, Bootstrap bootStrap) { - super(uri, bootStrap); - reconnectTimeouts = new CopyOnWriteArraySet<>(); - // init(); - } - - @Override - public void init() { - if (inited.compareAndSet(false, true)) { - Channel channel = connect(); - rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT, this); - // cache protocol information, so we can use it in DecoderHandler - String protocolName = getUri().getProtocol(); - rpcChannel.setAttribute(Constants.PROTOCOL_ATTR_KEY, protocolName); - } - } - - @Override - public RpcChannel getRpcChannel() throws TransportException { - if (rpcChannel == null || !rpcChannel.isActive()) { - synchronized (this) { - LOGGER.debug("SingleChannelGroup getChannel start"); - if (rpcChannel == null || !rpcChannel.isActive()) { - LOGGER.info("Get RpcChannel from SingleRpcChannelGroup, the original RpcChannel is not active. " - + "Will create new, remoteAddress {}, rpcChannel {}.", getUri().getAddress(), rpcChannel); - if (rpcChannel != null) { - LOGGER.info("Close old rpcChannel when create new, old RpcChannel {}," + "RemoteAddress {}", - rpcChannel, getUri().getAddress()); - // close old channel, use thread to reduce time consuming - new Thread(rpcChannel::close).start(); - } - // create new channel - RpcChannel newChannel = new LongRpcChannel(connect(), ChannelSide.CLIENT); - newChannel.setAttribute(Constants.PROTOCOL_ATTR_KEY, getUri().getProtocol()); - returnRpcChannel(newChannel); - } - } - } - LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY) - .set(rpcChannel.channel().id().asLongText(), Thread.currentThread().getContextClassLoader()); - return rpcChannel; - } - - /** - * When return to single long channel group, it means check and update the old RpcChannel - * - * @param rpcChannel - */ - @Override - public void returnRpcChannel(RpcChannel rpcChannel) { - if (rpcChannel != this.rpcChannel) { - synchronized (this) { - if (rpcChannel != this.rpcChannel) { - this.rpcChannel = rpcChannel; - } - } - } - } - - // 当前仅在HeartBeatHandler与RpcHandler中调用,加上根据Netty的Channel与EventLoop映射关系,能保证单线程执行 - @Override - public void removeRpcChannel(RpcChannel rpcChannel) { - if (rpcChannel != this.rpcChannel) { // there is a newer rpcChannel, not need remove - return; - } - - // reconnect - Timeout timeout = - TimerHolder.getTimer().newTimeout(new ReconnectTask(this, rpcChannel), 0, TimeUnit.MILLISECONDS); - reconnectTimeouts.add(timeout); - } - - @Override - public int rpcChannelCount() { - return CHANNEL_NUM; - } - - @Override - public void close() { - for (Timeout timeout : reconnectTimeouts) { - timeout.cancel(); - } - if (rpcChannel != null) { - rpcChannel.close(); - } - } - - @Override - public Set allRpcChannels() { - Set rpcChannels = new HashSet<>(); - rpcChannels.add(rpcChannel); - return rpcChannels; - } - - public Set getReconnectTimeouts() { - return reconnectTimeouts; - } - - /** - * ReconnectTask will execute reconnect - */ - protected static class ReconnectTask implements TimerTask { - private static final Logger LOGGER = LoggerFactory.getLogger(ReconnectTask.class); - - private final SingleRpcChannelGroup channelGroup; - - private final RpcChannel needReconChannel; - - public ReconnectTask(SingleRpcChannelGroup singleRpcChannelGroup, RpcChannel needReconChannel) { - this.channelGroup = singleRpcChannelGroup; - this.needReconChannel = needReconChannel; - } - - @Override - public void run(Timeout timeout) throws Exception { - - // Prevent concurrency problems with other threads, such as user request thread - synchronized (channelGroup) { - try { - LOGGER.debug("SingleChannelGroup reconnect start"); - // create new channel and close old channel - RpcChannel newChannel = channelGroup.getRpcChannel(); - if (newChannel != needReconChannel) { - LOGGER.info( - "Reconnect rpc channel success, channel not same, not need reconnect, " - + "need connect channel {}, new channel {}, remoteAddress {}", - needReconChannel, newChannel, channelGroup.getRpcChannel().getRemoteAddress()); - return; - } - // use for no heartbeat protocol? - LOGGER.info("Will close and reconnect channel {}, remoteAddress {}", needReconChannel, - needReconChannel.getRemoteAddress()); - - // close old channel, use thread to reduce time consuming - new Thread(needReconChannel::close).start(); - - newChannel = new LongRpcChannel(channelGroup.connect(), ChannelSide.CLIENT, channelGroup); - channelGroup.returnRpcChannel(newChannel); - LOGGER.info("Reconnect rpc channel success, remoteAddress {}", newChannel.getRemoteAddress()); - } catch (TransportException e) { - Integer reconnectedTimes = (Integer) needReconChannel.getAttribute(Constants.RECONNECTED_TIMES_KEY); - if (reconnectedTimes == null) { - reconnectedTimes = 0; - } - if (reconnectedTimes >= Constants.MAX_RECONNECT_TIMES) { - LOGGER.info( - "Maximum number {} of connection retries reached, reconnect failed: " - + "remoteHost {}, remotePort {}", - channelGroup.getUri().getHost(), channelGroup.getUri().getPort(), e); - return; - } - needReconChannel.setAttribute(Constants.RECONNECTED_TIMES_KEY, ++reconnectedTimes); - LOGGER.info("Reconnect to remote {}:{} failed, retry times {}, will retry after {}s", - channelGroup.getUri().getHost(), channelGroup.getUri().getPort(), reconnectedTimes, - Constants.RECONNECT_RETRY_INTERVAL_AFTER_FAILED); - // return after 10s - Timeout timeout1 = timeout.timer().newTimeout(timeout.task(), - Constants.RECONNECT_RETRY_INTERVAL_AFTER_FAILED, TimeUnit.SECONDS); - channelGroup.getReconnectTimeouts().add(timeout1); - } finally { - channelGroup.getReconnectTimeouts().remove(timeout); - } - } - } - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/concurrent/DelegateThreadFactory.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/concurrent/DelegateThreadFactory.java deleted file mode 100644 index 398166d9..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/concurrent/DelegateThreadFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.concurrent; - -import com.baidu.cloud.thirdparty.netty.util.concurrent.DefaultThreadFactory; - -import java.util.concurrent.ThreadFactory; - -public class DelegateThreadFactory extends DefaultThreadFactory { - - private ThreadFactory delegate; - - public DelegateThreadFactory(ThreadFactory delegate, String poolName, boolean daemon) { - super(poolName, daemon); - this.delegate = delegate; - } - - @Override - protected Thread newThread(Runnable r, String name) { - Thread thread = delegate.newThread(r); - if (thread != null) { - thread.setName(name); - } - return thread; - } - -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DecoderHandler.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DecoderHandler.java deleted file mode 100644 index 1116b355..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DecoderHandler.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.channel.SimpleChannelInboundHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Set; - -/** - * Protocol decoding in the IO thread Created by liuruisen on 2020/2/3. - */ -public class DecoderHandler extends SimpleChannelInboundHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DecoderHandler.class); - - @Override - protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { - - ChannelAttribute attribute = ctx.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute == null) { - throw new TransportException("Netty Channel don't have ChannelAttribute instance, Channel Illegal"); - } - - // set currentThread's contextClassLoader to requestThread's ClassLoader - // this make Protostuff get the correct Schema bound with ClassLoader - ClassLoader classLoader = LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY) - .get(ctx.channel().id().asLongText()); - if (classLoader != null && attribute.getRpcChannel().side().equals(ChannelSide.CLIENT)) { - Thread.currentThread().setContextClassLoader(classLoader); - } else if (attribute.getRpcChannel().side().equals(ChannelSide.CLIENT)) { - LOGGER.warn("Class Loader related to channel {} is null, plz check", ctx.channel().id().asLongText()); - } - - RpcChannel rpcChannel = attribute.getRpcChannel(); - String remoteAddress = ""; - try { - if (rpcChannel.getRemoteAddress() != null) { - remoteAddress = rpcChannel.getRemoteAddress().getAddress().getHostAddress() + ":" - + rpcChannel.getRemoteAddress().getPort(); - } - } catch (Exception e) { - LOGGER.warn("Get remote addr from channel failed, remote addr value will be null, cause by: {}", - e.getMessage()); - } - - long receiveTime = System.currentTimeMillis(); - long msgSize = msg.readableBytes(); - - LOGGER.debug("Receive msg from {}, size {}", remoteAddress, msgSize); - - if (msg != null && msg.readableBytes() > 0) { - attribute.getDynamicByteBuf().addBuffer(msg.retain()); - } - - // protocol decode and fire message - while (attribute.getDynamicByteBuf().readableBytes() > 0) { - try { - ThreadLocalChannelContext.getContext().setChannel(attribute.getRpcChannel().channel()); - // protocol decode - MsgBase msgBase = protocolDecode(attribute, attribute.getDynamicByteBuf()); - - // fire message - if (msgBase != null) { - LogUtils.addLogTimeAttachment(msgBase, Constants.RECEIVE_BYTE_MSG_TIME_KEY, receiveTime); - msgBase.getNoneAdditionKv().put(Constants.REMOTE_ADDRESS_KEY, remoteAddress); - LogUtils.addLogTimeAttachment(msgBase, Constants.BEFORE_DECODE_HEADER_TIME_KEY, receiveTime); - LogUtils.addLogTimeAttachment(msgBase, Constants.DECODE_HEADER_COST, - System.currentTimeMillis() - receiveTime); - - if (msgBase.getAttachmentKv() == null) { - msgBase.setAttachmentKv(new HashMap<>()); - } - // fixbug: remote address is illegal in server side, will add remote address to RpcContext - try { - msgBase.getAttachmentKv().put(RpcContext.REMOTE_HOST_KEY, - rpcChannel.getRemoteAddress().getAddress().getHostAddress()); - msgBase.getAttachmentKv().put(RpcContext.REMOTE_PORT_KEY, - rpcChannel.getRemoteAddress().getPort()); - } catch (Exception e) { - LOGGER.debug( - "Get remote addr from channel failed, remote addr value will be null, " + "cause by: {}", - e.getMessage()); - } - - ctx.fireChannelRead(msgBase); - } - - } catch (CodecException e) { // know and unknow decode failed - if (e.getCode().equals(CodecException.PROTOCOL_DECODE_NOTENOUGHDATA_EXCEPTION) - || e.getCode().equals(CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION)) { // retry decode - // next time - LOGGER.warn( - "Decode header with the byteBuf failed, will retry: side {}, remoteAddr {}, " - + "recvMsgTime {}, size {}, cause by {}.", - rpcChannel.side(), remoteAddress, receiveTime, msgSize, e.getMessage()); - break; - } else { // throw decode exception - LOGGER.warn( - "Decode header with the byteBuf failed: side {}, remoteAddr {}, " - + "recvMsgTime {}, size {}, the last exception is {}.", - rpcChannel.side(), remoteAddress, receiveTime, msgSize, e.getMessage()); - throw e; - } - } finally { - ThreadLocalChannelContext.removeContext(); - } - } - - } - - private MsgBase protocolDecode(ChannelAttribute attribute, DynamicCompositeByteBuf byteBuf) throws CodecException { - // decode know protocol - try { - if (attribute.getChannelProtocol() != null - && !attribute.getChannelProtocol().equals(Constants.UNSPECIFIED_PROTOCOL)) { - return knowProtocolDecode(attribute.getChannelProtocol(), byteBuf); - } - } catch (CodecException e) { - // protocol not match will retry decode use unknow protocol - // Insufficient data exception, wait and decoder later - if (e.getCode().equals(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION)) { - attribute.resetChannelProtocol(Constants.UNSPECIFIED_PROTOCOL); - } else { // protocol decode failed, throw exception - throw e; - } - } - - // decode unKnow protocol, Protocol is not specified - if (attribute.getChannelProtocol() == null - || attribute.getChannelProtocol().equals(Constants.UNSPECIFIED_PROTOCOL)) { - return unKnowProtocolDecode(attribute, byteBuf); - } - - return null; - } - - /** - * Decode message with know protocol May throw CodecException, when decode fail - * - * @param protocolName - * @param byteBuf - * @return - * @throws CodecException - */ - private MsgBase knowProtocolDecode(String protocolName, DynamicCompositeByteBuf byteBuf) throws CodecException { - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName); - return protocol.getDecoder().decode(byteBuf); - } - - /** - * Try decoding using all protocols - * - * @param byteBuf - * @return - * @throws CodecException - */ - private MsgBase unKnowProtocolDecode(ChannelAttribute attribute, DynamicCompositeByteBuf byteBuf) - throws CodecException { - MsgBase msgObj = null; - Set protocols = ExtensionLoader.getInstance(Protocol.class).getSupportedExtensions(); - int protocolNum = 1; - // all support protocols - for (String protocolName : protocols) { - try { - msgObj = knowProtocolDecode(protocolName, byteBuf); - if (msgObj != null) { - // specified protocol, cache protocol to improve decoding efficiency - attribute.resetChannelProtocol(protocolName); - break; - } - } catch (CodecException e) { - if (e.getCode().equals(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION)) { // retry another protocol - // LOGGER.debug("Use {} to decode byte, failed {}", protocolName, e.getMessage()); - if (protocolNum < protocols.size()) { - continue; - } - throw e; - } - - // match protocol but exception - // specified protocol, cache protocol to improve decoding efficiency - attribute.resetChannelProtocol(protocolName); - LOGGER.debug( - "Attempts to use multiple protocols to decode failed. " - + "The reason for the last failed attempt is: protocol {}, message {}", - protocolName, e.getMessage()); - throw e; // notEnoughData or other decode exception - - } finally { - protocolNum++; - } - } - - return msgObj; - } - -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DirectMemoryReporter.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DirectMemoryReporter.java deleted file mode 100644 index ecb25a6b..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/DirectMemoryReporter.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.thirdparty.netty.util.internal.PlatformDependent; -import com.baidu.cloud.thirdparty.springframework.util.ReflectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 收集直接内存占用数据 Created by liuruisen on 2021/12/13. - */ -public class DirectMemoryReporter { - - private static final Logger LOGGER = LoggerFactory.getLogger(DirectMemoryReporter.class); - - private AtomicLong directMemory; - - private ScheduledThreadPoolExecutor schedulePool; - - public DirectMemoryReporter() { - init(); - report(); - } - - private void init() { - try { - Field field = ReflectionUtils.findField(PlatformDependent.class, "DIRECT_MEMORY_COUNTER"); - field.setAccessible(true); - directMemory = (AtomicLong) field.get(PlatformDependent.class); - } catch (IllegalAccessException e) { - LOGGER.warn("Get DIRECT_MEMORY_COUNTER from PlatformDependent failed.", e); - return; - } - schedulePool = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("DirectMem-")); - } - - public void report() { - if (schedulePool == null) { - return; - } - schedulePool.scheduleAtFixedRate(() -> { - try { - if (directMemory != null) { - LOGGER.info("netty_direct_memory: {}B", directMemory.get()); - LOGGER.info("netty_direct_memory: {}K", directMemory.get() / 1024); - } - } catch (Throwable e) { - LOGGER.warn("Get DIRECT_MEMORY_COUNTER from directMemory failed.", e); - } - - }, 0, 1, TimeUnit.MINUTES); - } - - public void close() { - if (schedulePool != null) { - schedulePool.shutdownNow(); - } - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/EncoderHandler.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/EncoderHandler.java deleted file mode 100644 index fa6c3913..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/EncoderHandler.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.api.utils.LogUtils; -import com.baidu.cloud.starlight.api.utils.StringUtils; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandler; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.handler.codec.MessageToByteEncoder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Protocol encoding in the IO thread Created by liuruisen on 2020/2/3. - */ -@ChannelHandler.Sharable -public class EncoderHandler extends MessageToByteEncoder { - - private static final Logger LOGGER = LoggerFactory.getLogger(EncoderHandler.class); - - @Override - protected void encode(ChannelHandlerContext channelHandlerContext, MsgBase msgBase, ByteBuf byteBuf) - throws Exception { - - ChannelAttribute attribute = channelHandlerContext.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute == null) { - throw new TransportException("Netty Channel don't have ChannelAttribute instance, Channel Illegal"); - } - - // set currentThread's contextClassLoader to requestThread's ClassLoader - // this make Protostuff get the correct Schema bound with ClassLoader - ClassLoader classLoader = LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY) - .get(channelHandlerContext.channel().id().asLongText()); - if (classLoader != null && attribute.getRpcChannel().side().equals(ChannelSide.CLIENT)) { - Thread.currentThread().setContextClassLoader(classLoader); - } else if (attribute.getRpcChannel().side().equals(ChannelSide.CLIENT)) { - LOGGER.error("Class Loader related to channel {} is null, plz check", - channelHandlerContext.channel().id().asLongText()); - } - - if (msgBase == null) { - throw new CodecException(TransportException.BODY_NULL_EXCEPTION, "Message is null, cannot encode!"); - } - - // 记录等待io线程执行的时间 - Object timeBeforeIoExec = msgBase.getNoneAdditionKv().get(Constants.BEFORE_IO_THREAD_EXECUTE_TIME_KEY); - if (timeBeforeIoExec instanceof Long) { - LogUtils.addLogTimeAttachment(msgBase, Constants.WAIT_FOR_IO_THREAD_COST_KEY, - System.currentTimeMillis() - ((Long) timeBeforeIoExec)); - } - - String protocolName = msgBase.getProtocolName(); - if (StringUtils.isBlank(protocolName)) { - throw new CodecException("Cannot encode the message, protocol info is null in the message"); - } - - ProtocolEncoder encoder = ExtensionLoader.getInstance(Protocol.class).getExtension(protocolName).getEncoder(); - // Protocol encode - ByteBuf encodeResult = null; - try { - ThreadLocalChannelContext.getContext().setChannel(attribute.getRpcChannel().channel()); - long beforeEncodeHeaderTime = System.currentTimeMillis(); - LogUtils.addLogTimeAttachment(msgBase, Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeHeaderTime); - if (msgBase instanceof Request) { // server端感知客户端发送请求的近似时间,用于超时原因推断,notice:不随调用链向下传递 - msgBase.getAttachmentKv().put(Constants.BEFORE_ENCODE_HEADER_TIME_KEY, beforeEncodeHeaderTime); - } - encodeResult = encoder.encode(msgBase); - LogUtils.addLogTimeAttachment(msgBase, Constants.ENCODE_HEADER_COST, - System.currentTimeMillis() - beforeEncodeHeaderTime); - if (msgBase instanceof Response) { // server side: the request - response is complete, record acc log - LogUtils.addLogTimeAttachment(msgBase, Constants.RETURN_RESPONSE_TIME_KEY, System.currentTimeMillis()); - LogUtils.recordAccessLog(((Response) msgBase).getRequest(), (Response) msgBase); - } - if (msgBase instanceof Request) { // client side: record time before call server - LogUtils.addLogTimeAttachment(msgBase, Constants.BEFORE_SERVER_EXECUTE_TIME_KEY, - System.currentTimeMillis()); - } - // NOTICE: 涉及一次内存拷贝,可优化? - byteBuf.writeBytes(encodeResult); - LOGGER.debug("Send msg to {}, size {}", channelHandlerContext.channel().remoteAddress(), - byteBuf.readableBytes()); - } catch (CodecException e) { - LOGGER.warn("Protocol encode fail, protocol: " + protocolName, e); - throw e; - } finally { - // 此处进行encodeResult release的操作,encodeResult被writeBytes后将无用 - if (encodeResult != null && encodeResult.refCnt() > 0) { - encodeResult.release(); - } - ThreadLocalChannelContext.removeContext(); - } - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandler.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandler.java deleted file mode 100644 index 3a0a9b72..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFutureListener; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.channel.ChannelInboundHandlerAdapter; -import com.baidu.cloud.thirdparty.netty.handler.timeout.IdleStateEvent; -import com.baidu.cloud.thirdparty.netty.util.AttributeKey; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Check if the channel is Health, maintain long connection. ClientSide: When read idle detected send Heartbeat Msg. - * ServerSide: When idle detected close Channel. Created by liuruisen on 2020/2/3. - */ -public class HeartbeatHandler extends ChannelInboundHandlerAdapter { - private static final Logger LOGGER = LoggerFactory.getLogger(HeartbeatHandler.class); - - /** - * AttributeKey for HeartBeat Fail times - **/ - public static final AttributeKey HEARTBEAT_FAIL_TIMES = AttributeKey.valueOf("heartbeat"); - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - if (evt instanceof IdleStateEvent) { - ChannelAttribute attribute = ctx.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute.getRpcChannel().side().equals(ChannelSide.CLIENT)) { // client side: trigger heartbeat - if (ctx.channel().attr(HEARTBEAT_FAIL_TIMES).get() == null) { - ctx.channel().attr(HEARTBEAT_FAIL_TIMES).set(0); - } - triggerHeartbeat(ctx); - } else { // server side: close - LOGGER.info("Server side, No IO operation for a long time, close the connection, remoteAddr {}", - ctx.channel().remoteAddress()); - ctx.channel().close(); - } - } else { - super.userEventTriggered(ctx, evt); - } - } - - private void triggerHeartbeat(ChannelHandlerContext context) { - ChannelAttribute attribute = context.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute == null || attribute.getRpcChannel() == null) { - throw new StarlightRpcException("AttributeKey value is null"); - } - - RpcChannel rpcChannel = attribute.getRpcChannel(); - HeartbeatTrigger heartbeatTrigger = null; - if (attribute.getChannelProtocol() != null - && !attribute.getChannelProtocol().equals(Constants.UNSPECIFIED_PROTOCOL)) { - Protocol protocol = - ExtensionLoader.getInstance(Protocol.class).getExtension(attribute.getChannelProtocol()); - heartbeatTrigger = protocol.getHeartbeatTrigger(); - } - - if (heartbeatTrigger != null) { // Protocol support heartbeat, send heartbeat msg - Request heartbeatRequest = heartbeatTrigger.heartbeatRequest(); - ChannelFuture channelFuture = context.channel().writeAndFlush(heartbeatRequest); - channelFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if (!channelFuture.isSuccess()) { // send fail, add heartbeat fail times - addHeartbeatFailTimes(context.channel()); - LOGGER.info("Send heartbeat Ping message to remote {} failed.", rpcChannel.getRemoteAddress(), - channelFuture.cause()); - } else { - // send success, channel is alive, clear heartbeat fail times - // fixme 要不要移动到handleHeartbeatResponse - clearHeartbeatFailTimes(context.channel()); - } - } - }); - } else { // Protocol not support heartbeat, add failTimes - addHeartbeatFailTimes(context.channel()); - } - - // reconnect异常时,打印异常日志,不做处理,等待程序正常执行 - if (context.channel().attr(HEARTBEAT_FAIL_TIMES).get() >= Constants.MAX_HEARTBEAT_TIMES_VALUE) { - try { - rpcChannel.reconnect(); - } catch (Exception e) { - LOGGER.debug("Heartbeat Reconnect Failed", e); - } - } - } - - private void addHeartbeatFailTimes(Channel channel) { - channel.attr(HEARTBEAT_FAIL_TIMES).set(channel.attr(HEARTBEAT_FAIL_TIMES).get() + 1); - } - - private void clearHeartbeatFailTimes(Channel channel) { - channel.attr(HEARTBEAT_FAIL_TIMES).set(0); - } - - // handle heartbeat request and return heartbeat response - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - ctx.channel().attr(HEARTBEAT_FAIL_TIMES).set(0); - if (!(msg instanceof MsgBase)) { - ctx.fireChannelRead(msg); - return; - } - - if (!((MsgBase) msg).isHeartbeat()) { - ctx.fireChannelRead(msg); - return; - } - - ChannelAttribute attribute = ctx.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute == null || attribute.getRpcChannel() == null) { - throw new TransportException(TransportException.RPC_CHANNEL_NULL_EXCEPTION, - "RpcChannel in Channel is null"); - } - - RpcChannel rpcChannel = attribute.getRpcChannel(); - if (msg instanceof Request) { // heartbeat request - handleHeartbeatRequest(rpcChannel, (Request) msg); - } - - if (msg instanceof Response) { // heartbeat response - handleHeartbeatResponse(rpcChannel, (Response) msg); - } - } - - private void handleHeartbeatRequest(RpcChannel rpcChannel, Request request) { - // response pong message - Protocol protocol = ExtensionLoader.getInstance(Protocol.class).getExtension(request.getProtocolName()); - if (protocol == null) { - throw new TransportException(TransportException.HEARTBEAT_EXCEPTION, - "Heartbeat request protocol is not supported"); - } - Response response = protocol.getHeartbeatTrigger().heartbeatResponse(); - response.setId(request.getId()); - rpcChannel.send(response); - } - - private void handleHeartbeatResponse(RpcChannel rpcChannel, Response response) { - // do nothing - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyClient.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyClient.java deleted file mode 100644 index 0e70258e..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyClient.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.RpcContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannelGroup; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.starlight.transport.channel.PooledRpcChannelGroup; -import com.baidu.cloud.starlight.transport.channel.SingleRpcChannelGroup; -import com.baidu.cloud.starlight.transport.concurrent.DelegateThreadFactory; -import com.baidu.cloud.starlight.transport.utils.TimerHolder; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.buffer.PooledByteBufAllocator; -import com.baidu.cloud.thirdparty.netty.channel.ChannelInitializer; -import com.baidu.cloud.thirdparty.netty.channel.ChannelOption; -import com.baidu.cloud.thirdparty.netty.channel.EventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.epoll.Epoll; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollChannelOption; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollEventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollMode; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollSocketChannel; -import com.baidu.cloud.thirdparty.netty.channel.nio.NioEventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.socket.SocketChannel; -import com.baidu.cloud.thirdparty.netty.channel.socket.nio.NioSocketChannel; -import com.baidu.cloud.thirdparty.netty.handler.timeout.IdleStateHandler; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import com.baidu.cloud.thirdparty.netty.util.TimerTask; -import com.baidu.cloud.thirdparty.netty.util.concurrent.DefaultThreadFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/2/3. - */ -public class NettyClient implements ClientPeer { - private static final Logger LOGGER = LoggerFactory.getLogger(NettyClient.class); - - private RpcChannelGroup rpcChannelGroup; - - private Bootstrap bootstrap; - - private Processor processor; - - private static volatile EventLoopGroup eventLoopGroup; // static: shared by all NettyClient - - private URI uri; - - private volatile PeerStatus status; - - private ThreadFactory threadFactory; - - // 存储NettyClient这个类的实例信息,以ip:port为key - private static final Set INSTANCE_SET = new CopyOnWriteArraySet<>(); - - // init eventLoopGroup - static { - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - if (eventLoopGroup == null) { - return; - } - - if (INSTANCE_SET.isEmpty()) { - LOGGER.info("All the instance of NettyClient is closed, will shutdown eventloop gracefully"); - eventLoopGroup.shutdownGracefully(); - } - - long beginShutdownTime = System.currentTimeMillis(); - - for (;;) { - - if (INSTANCE_SET.isEmpty()) { - LOGGER.info("All the instance of NettyClient is closed, will shutdown eventloop gracefully"); - eventLoopGroup.shutdownGracefully(); - break; - } - - if ((System.currentTimeMillis() - beginShutdownTime) > 1000 * 60 * 2) { // max wait 2min - LOGGER.info("Reach the max shutdown time, will shutdown enventloop gracefully"); - eventLoopGroup.shutdownGracefully(); - break; - } - - try { - TimeUnit.MILLISECONDS.sleep(1000); - } catch (InterruptedException e) { - // ignore - } - } - })); - } - - // Uri: Ip:port + config - public NettyClient(URI uri) { - - this.uri = uri; - INSTANCE_SET.add(this.uri.getAddress()); - } - - @Override - public RpcChannelGroup getChannelGroup() { - return this.rpcChannelGroup; - } - - public RpcChannelGroup getSseChannelGroup() { - RpcChannelGroup singleRpcChannelGroup = new SingleRpcChannelGroup(getUri(), bootstrap); - singleRpcChannelGroup.init(); - return singleRpcChannelGroup; - } - - @Override - public void connect() { - // 在StarlightClient中调用,且StarlightClient中设置了并发保护,此处暂未考虑并发问题 - rpcChannelGroup = rpcChannelGroup( - getUri().getParameter(Constants.RPC_CHANNEL_TYPE_KEY, Constants.DEFAULT_RPC_CHANNEL_TYPE_VALUE)); - rpcChannelGroup.init(); - } - - @Override - public void request(Request request, RpcCallback callback) throws TransportException { - if (rpcChannelGroup == null) { - throw new TransportException("RpcChannelGroup of NettyClient is null, plz check"); - } - boolean isSse = SpringRestSseProtocol.PROTOCOL_NAME.equals(request.getProtocolName()); - // TODO 不用连接池 是不是可以的 - RpcChannel rpcChannel = isSse ? getSseChannelGroup().getRpcChannel() : rpcChannelGroup.getRpcChannel(); - - // 如果是SSE,使用SSE连接池的连接,并给获取到的连接设置协议,便于解码器DecoderHandler识别协议 - if (isSse) { - rpcChannel.setAttribute(Constants.PROTOCOL_ATTR_KEY, SpringRestSseProtocol.PROTOCOL_NAME); - callback.addRpcChannel(rpcChannel); - rpcChannel.setAttribute(Constants.SSE_CALLBACK_ATTR_KEY, callback); - } - - try { - int requestTimeoutMills = Constants.REQUEST_TIMEOUT_VALUE; // default - - if (request.getServiceConfig() != null && request.getServiceConfig().getInvokeTimeoutMills() != null - && request.getServiceConfig().getInvokeTimeoutMills() > 0) { - requestTimeoutMills = request.getServiceConfig().getInvokeTimeoutMills(); - } - - if (RpcContext.getContext().getRequestTimeoutMills() != null - && RpcContext.getContext().getRequestTimeoutMills() > 0) { - requestTimeoutMills = RpcContext.getContext().getRequestTimeoutMills(); - } - // carry request time out to server, remember not set it in server side RpcContext - request.getAttachmentKv().put(Constants.REQUEST_TIMEOUT_KEY, requestTimeoutMills); - - Timeout timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - RpcCallback rpcCallback = rpcChannel.removeCallback(request.getId()); - if (rpcCallback == null) { - return; - } - rpcCallback.onError(StarlightRpcException.timeoutException(request, getUri().getAddress())); - } - }, requestTimeoutMills, TimeUnit.MILLISECONDS); - callback.addTimeout(timeout); - rpcChannel.putCallback(request.getId(), callback); // put callback to rpc channel - rpcChannel.send(request); // send request - } finally { - // return rpc channel to reuse - if (!isSse) { - // sse不需要在这里归还连接 - rpcChannelGroup.returnRpcChannel(rpcChannel); - } - } - } - - @Override - public void init() { - if (eventLoopGroup == null) { - synchronized (this) { - if (eventLoopGroup == null) { - int ioThreadNum = uri.getParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS_VALUE); - int ioRatio = uri.getParameter(Constants.NETTY_IO_RATIO_KEY, Constants.DEFAULT_NETTY_IO_RATIO); - if (Epoll.isAvailable()) { - if (threadFactory == null) { - eventLoopGroup = - new EpollEventLoopGroup(ioThreadNum, new DefaultThreadFactory("client-epoll", true)); - } else { - eventLoopGroup = new EpollEventLoopGroup(ioThreadNum, - new DelegateThreadFactory(threadFactory, "client-epoll", true)); - } - ((EpollEventLoopGroup) eventLoopGroup).setIoRatio(ioRatio); - } else { - if (threadFactory == null) { - eventLoopGroup = - new NioEventLoopGroup(ioThreadNum, new DefaultThreadFactory("client-nio", true)); - } else { - eventLoopGroup = new NioEventLoopGroup(ioThreadNum, - new DelegateThreadFactory(threadFactory, "client-epoll", true)); - } - ((NioEventLoopGroup) eventLoopGroup).setIoRatio(ioRatio); - } - } - } - } - - bootstrap = new Bootstrap(); - bootstrap.group(eventLoopGroup); - if (Epoll.isAvailable()) { - bootstrap.channel(EpollSocketChannel.class); - bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); - LOGGER.debug("NettyClient use Epoll Mode"); - } else { - bootstrap.channel(NioSocketChannel.class); - LOGGER.debug("NettyClient use Nio Mode"); - } - - bootstrap.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE).option(ChannelOption.TCP_NODELAY, Boolean.TRUE) - .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, - getUri().getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.CONNECT_TIMEOUT_VALUE)); - - final ChannelInitializer initializer = new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(new DecoderHandler()); // inbound 1 DecoderHandler - if (getUri().getParameter(Constants.CONNECT_KEEPALIVE_ENABLED_KEY, - Constants.CONNECT_KEEPALIVE_ENABLED_VALUE)) { - ch.pipeline() - .addLast(new IdleStateHandler( - getUri().getParameter(Constants.READ_IDLE_TIMEOUT_KEY, Constants.READ_IDLE_TIMEOUT_VALUE), - 0, 0, TimeUnit.SECONDS)) - .addLast(new HeartbeatHandler()); // inbound 2 heartbeatHandler - } - - ch.pipeline().addLast(new RpcHandler(NettyClient.this)) // inbound 3 RpcHandler - .addLast(new EncoderHandler()); // outbound EncoderHandler - } - }; - bootstrap.handler(initializer); - } - - @Override - public URI getUri() { - return this.uri; - } - - @Override - public void close() { - if (processor != null) { - processor.close(); - } - if (rpcChannelGroup != null) { - rpcChannelGroup.close(); - } - - INSTANCE_SET.remove(this.uri.getAddress()); - } - - @Override - public void setProcessor(Processor processor) { - this.processor = processor; - } - - @Override - public Processor getProcessor() { - return processor; - } - - // 当前spi机制无法进行有参数的构造函数的扩展实现,替换方案为switch方式 - private RpcChannelGroup rpcChannelGroup(String channelType) { - if (channelType != null) { - switch (channelType) { - case "long": - return new SingleRpcChannelGroup(getUri(), bootstrap); - case "pool": - return new PooledRpcChannelGroup(getUri(), bootstrap); - default: - throw new StarlightRpcException( - "RpcChannelGroup type {" + channelType + "} is illegal: not support."); - } - } - throw new StarlightRpcException("RpcChannelGroup type is null"); - } - - @Override - public PeerStatus status() { - return this.status; - } - - @Override - public void gracefullyShutdown(long quietPeriod, long timeout) { - - try { - updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, System.currentTimeMillis())); - - // wait for all request has been done - if (timeout > 0) { - long shutdownTimeoutTime = System.currentTimeMillis() + timeout * 1000; - for (;;) { - int unfinishedCallbackNum = 0; - for (RpcChannel rpcChannel : rpcChannelGroup.allRpcChannels()) { - if (rpcChannel != null) { - unfinishedCallbackNum = unfinishedCallbackNum + rpcChannel.allCallbacks().size(); - } - } - - if (getProcessor().allWaitTaskCount().equals(0) && unfinishedCallbackNum == 0) { - LOGGER.info("NettyClient has processed all requests, shutdown. RemoteAddr {}", - getUri().getAddress()); - break; - } - - if (System.currentTimeMillis() >= shutdownTimeoutTime) { - LOGGER.info( - "NettyClient reach the maximum timeout time, force shutdown. RemoteAddr {}." - + "Number of unfinished task {}, Number of unfinished request {}. " - + "Will response timeout", - getUri().getAddress(), getProcessor().allWaitTaskCount(), unfinishedCallbackNum); - for (RpcChannel rpcChannel : rpcChannelGroup.allRpcChannels()) { - if (rpcChannel.allCallbacks() != null && rpcChannel.allCallbacks().size() > 0) { - for (RpcCallback rpcCallback : rpcChannel.allCallbacks().values()) { - rpcCallback.onError(StarlightRpcException.timeoutException(rpcCallback.getRequest(), - getUri().getAddress())); - } - rpcChannel.allCallbacks().clear(); - } - } - break; - } - - try { - TimeUnit.MILLISECONDS.sleep(100); - } catch (InterruptedException e) { - // ignore - } - } - } - - close(); - - updateStatus(new PeerStatus(PeerStatus.Status.SHUTDOWN, System.currentTimeMillis())); - } catch (Exception e) { - LOGGER.error("An exception occur when NettyClient shutdownGracefully.", e); - } - } - - @Override - public synchronized void updateStatus(PeerStatus newStatus) { - if (status == null) { - LOGGER.debug("Update {} status from {} to {}", getUri().getAddress(), status, newStatus); - status = newStatus; - return; - } - - // FIXME 状态更新时是否要考虑并发的问题 - if (PeerStatus.Status.SHUTTING_DOWN.equals(status.getStatus()) - && PeerStatus.Status.OUTLIER.equals(newStatus.getStatus())) { - LOGGER.warn("Forbidden to change status of ClientPeer {} from SHUTTINGDOWN to OUTLIER", - getUri().getAddress()); - return; - } - - if (PeerStatus.Status.SHUTDOWN.equals(status.getStatus()) - && PeerStatus.Status.OUTLIER.equals(newStatus.getStatus())) { - LOGGER.warn("Forbidden to change status of ClientPeer {} from SHUTDOWN to OUTLIER", getUri().getAddress()); - return; - } - - if (PeerStatus.Status.OUTLIER.equals(newStatus.getStatus()) - && PeerStatus.Status.OUTLIER.equals(status.getStatus())) { - LOGGER.warn("Forbidden to change status of ClientPeer {} from OUTLIER {} to OUTLIER {}", - getUri().getAddress(), status.getStatusRecordTime(), newStatus.getStatusRecordTime()); - return; - } - - LOGGER.debug("Update {} status from {} to {}", getUri().getAddress(), status, newStatus); - this.status = newStatus; - } - - public void setThreadFactory(ThreadFactory threadFactory) { - this.threadFactory = threadFactory; - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyServer.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyServer.java deleted file mode 100644 index 925391d9..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/NettyServer.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.protocol.stargate.StargateProtocol; -import com.baidu.cloud.starlight.transport.concurrent.DelegateThreadFactory; -import com.baidu.cloud.thirdparty.netty.bootstrap.ServerBootstrap; -import com.baidu.cloud.thirdparty.netty.buffer.PooledByteBufAllocator; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelInitializer; -import com.baidu.cloud.thirdparty.netty.channel.ChannelOption; -import com.baidu.cloud.thirdparty.netty.channel.EventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.SingleThreadEventLoop; -import com.baidu.cloud.thirdparty.netty.channel.epoll.Epoll; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollChannelOption; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollEventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollMode; -import com.baidu.cloud.thirdparty.netty.channel.epoll.EpollServerSocketChannel; -import com.baidu.cloud.thirdparty.netty.channel.nio.NioEventLoopGroup; -import com.baidu.cloud.thirdparty.netty.channel.socket.SocketChannel; -import com.baidu.cloud.thirdparty.netty.channel.socket.nio.NioServerSocketChannel; -import com.baidu.cloud.thirdparty.netty.handler.timeout.IdleStateHandler; -import com.baidu.cloud.thirdparty.netty.util.concurrent.DefaultThreadFactory; -import com.baidu.cloud.thirdparty.netty.util.concurrent.EventExecutor; -import com.baidu.cloud.thirdparty.netty.util.concurrent.GlobalEventExecutor; - -/** - * Created by liuruisen on 2020/2/3. - */ -public class NettyServer implements ServerPeer { - - private static final Logger LOGGER = LoggerFactory.getLogger(NettyServer.class); - - private Processor processor; - - private URI uri; - - private ServerBootstrap bootstrap; - - /** - * netty acceptor thread pool - */ - private EventLoopGroup parentGroup; - - /** - * netty io thread pool - */ - private EventLoopGroup childGroup; - - private Channel serverChannel; - - private Map rpcChannels; - - private volatile PeerStatus status; - - private DirectMemoryReporter reporter; - - private ThreadFactory threadFactory; - - public NettyServer(URI uri) { - this.uri = uri; - this.rpcChannels = new ConcurrentHashMap<>(); - } - - @Override - public void init() { - - bootstrap = new ServerBootstrap(); - int acceptThreadNum = uri.getParameter(Constants.ACCEPT_THREADS_KEY, Constants.DEFAULT_ACCEPTOR_THREAD_VALUE); - int ioThreadNum = uri.getParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS_VALUE); - int ioRatio = uri.getParameter(Constants.NETTY_IO_RATIO_KEY, Constants.DEFAULT_NETTY_IO_RATIO); - - if (Epoll.isAvailable()) { - if (threadFactory == null) { - parentGroup = - new EpollEventLoopGroup(acceptThreadNum, new DefaultThreadFactory("server-accept", false)); - childGroup = new EpollEventLoopGroup(ioThreadNum, new DefaultThreadFactory("server-epoll", false)); - - } else { - parentGroup = new EpollEventLoopGroup(acceptThreadNum, - new DelegateThreadFactory(threadFactory, "server-accept", false)); - childGroup = new EpollEventLoopGroup(acceptThreadNum, - new DelegateThreadFactory(threadFactory, "server-epoll", false)); - } - - ((EpollEventLoopGroup) parentGroup).setIoRatio(ioRatio); - ((EpollEventLoopGroup) childGroup).setIoRatio(ioRatio); - bootstrap.channel(EpollServerSocketChannel.class); - bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); - bootstrap.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED); - LOGGER.info("NettyServer use epoll mode."); - } else { - if (threadFactory == null) { - parentGroup = new NioEventLoopGroup(acceptThreadNum, new DefaultThreadFactory("server-accept", false)); - childGroup = new NioEventLoopGroup(ioThreadNum, new DefaultThreadFactory("server-nio", false)); - } else { - parentGroup = new NioEventLoopGroup(acceptThreadNum, - new DelegateThreadFactory(threadFactory, "server-accept", false)); - childGroup = new NioEventLoopGroup(acceptThreadNum, - new DelegateThreadFactory(threadFactory, "server-nio", false)); - } - - ((NioEventLoopGroup) parentGroup).setIoRatio(ioRatio); - ((NioEventLoopGroup) childGroup).setIoRatio(ioRatio); - bootstrap.channel(NioServerSocketChannel.class); - LOGGER.info("NettyServer use Nio mode."); - } - bootstrap.group(parentGroup, childGroup); - - // config - bootstrap.childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE); - bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); - bootstrap.childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE); - bootstrap.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE); - bootstrap.option(ChannelOption.SO_BACKLOG, Constants.SO_BACKLOG); - bootstrap.childOption(ChannelOption.SO_LINGER, Constants.SO_LINGER); - bootstrap.childOption(ChannelOption.SO_SNDBUF, Constants.SO_SNDBUF); - bootstrap.childOption(ChannelOption.SO_RCVBUF, Constants.SO_REVBUF); - - final ChannelInitializer initializer = new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(new DecoderHandler()); // inbound 1 DecoderHandler - if (getUri().getParameter(Constants.CONNECT_KEEPALIVE_ENABLED_KEY, - Constants.CONNECT_KEEPALIVE_ENABLED_VALUE)) { - ch.pipeline() - .addLast(new IdleStateHandler(0, 0, - getUri().getParameter(Constants.ALL_IDLE_TIMEOUT_KEY, Constants.ALL_IDLE_TIMEOUT_VALUE), - TimeUnit.SECONDS)) - .addLast(new HeartbeatHandler()); // inbound 2 heartbeatHandler - } - ch.pipeline().addLast(new RpcHandler(NettyServer.this)) // inbound 3 RpcHandler - .addLast(new EncoderHandler()); // outbound EncoderHandler - } - }; - bootstrap.childHandler(initializer); - } - - @Override - public void bind() { - // bind - ChannelFuture channelFuture = bootstrap.bind(getUri().getHost(), getUri().getPort()); - channelFuture.syncUninterruptibly(); - if (!channelFuture.isSuccess()) { - throw new TransportException(TransportException.BIND_EXCEPTION, - "Server bind to ip {" + getUri().getHost() + "}, port {" + getUri().getPort() + "} failed", - channelFuture.cause()); - } - LOGGER.info("Starlight server bind to ip {} port {}", getUri().getHost(), getUri().getPort()); - serverChannel = channelFuture.channel(); - // 测试用,上线不开启 - // if (!EnvUtils.isJarvisOnline()) { - // reporter = new DirectMemoryReporter(); - // } - updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - } - - @Override - public boolean isBound() { - return serverChannel.isOpen(); - } - - @Override - public URI getUri() { - return uri; - } - - @Override - public void close() { - try { - if (serverChannel != null) { - serverChannel.close(); - } - - if (processor != null) { - processor.close(); - } - - if (reporter != null) { - reporter.close(); - } - } finally { - if (parentGroup != null) { - parentGroup.shutdownGracefully(); - } - if (childGroup != null) { - childGroup.shutdownGracefully(); - } - } - } - - @Override - public void gracefullyShutdown(long quietPeriod, long timeout) { - LOGGER.info("Shutdown starlight server gracefully start"); - try { - // send shutdown event to all connected channels to notify the server is shutting down - LOGGER.info("Notify server shutting down to clients begin"); - long startTime = System.currentTimeMillis(); - for (Map.Entry entry : rpcChannels.entrySet()) { - try { - RpcResponse shuttingDownEvent = shuttingDownEvent(StargateProtocol.PROTOCOL_NAME); - Protocol protocol = - ExtensionLoader.getInstance(Protocol.class).getExtension(StargateProtocol.PROTOCOL_NAME); - protocol.getEncoder().encodeBody(shuttingDownEvent); - - entry.getValue().send(shuttingDownEvent); - LOGGER.info("Notify server shutting to {}", entry.getValue().channel().remoteAddress()); - } catch (TransportException e) { - // ignore and log - LOGGER.warn("Notify client SHUTTING_DOWN failed, remoteAddress: {}", entry.getKey(), e); - } - } - LOGGER.info("Notify server shutting down end, cost {} clients {}", System.currentTimeMillis() - startTime, - rpcChannels.size()); - - long shutdownTimeoutTime = System.currentTimeMillis() + timeout * 1000; - - // wait for quiet period pass, in this period server can receive little request and handle them - if (quietPeriod > 0) { - LOGGER.info("Wait for quiet period pass {}s", quietPeriod); - try { - TimeUnit.SECONDS.sleep(quietPeriod); - } catch (InterruptedException e) { - // ignore - } - } - - // set shutting down, server cannot handle any request - updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, System.currentTimeMillis())); - - // unbind, to prevent new connect - if (serverChannel != null) { - serverChannel.close(); - } - - // execute unfinished task and wait for the timeout to arrive - if (timeout > 0) { - for (;;) { - if (pendingTaskNum().equals(0) && getProcessor().allWaitTaskCount().equals(0)) { // whether the - // requests is - // completed - LOGGER.info("NettyServer has processed all requests, gracefully shutdown."); - break; - } - - if (System.currentTimeMillis() >= shutdownTimeoutTime) { - LOGGER.info("NettyServer reach the maximum timeout time, force shutdown. " - + "Number of unfinished request {}", getProcessor().allWaitTaskCount()); - break; - } - - try { - TimeUnit.MILLISECONDS.sleep(100); - } catch (InterruptedException e) { - // ignore - } - } - } - // execute processor shutdown & netty gracefully shutdown - if (processor != null) { - processor.close(); // the thread pool will shutdown now - } - updateStatus(new PeerStatus(PeerStatus.Status.SHUTDOWN, System.currentTimeMillis())); - } catch (Throwable e) { - LOGGER.warn("Shutdown starlight server gracefully failed, cause by: ", e); - } finally { - if (parentGroup != null) { - parentGroup.shutdownGracefully(); - } - if (childGroup != null) { - childGroup.shutdownGracefully(); - } - } - LOGGER.info("Shutdown starlight server gracefully end"); - } - - @Override - public void setProcessor(Processor processor) { - this.processor = processor; - } - - @Override - public Processor getProcessor() { - return processor; - } - - @Override - public Map rpcChannels() { - return this.rpcChannels; - } - - @Override - public PeerStatus status() { - return this.status; - } - - @Override - public void updateStatus(PeerStatus status) { - // server update status no need consider thread safe - this.status = status; - } - - private Integer pendingTaskNum() { - Integer pendingTaskNum = 0; - try { - for (EventExecutor eventExecutor : parentGroup) { - if (eventExecutor instanceof SingleThreadEventLoop) { - pendingTaskNum += ((SingleThreadEventLoop) eventExecutor).pendingTasks(); - } - } - LOGGER.debug("Parent event loop group pending task num {}", pendingTaskNum); - - for (EventExecutor eventExecutor : childGroup) { - if (eventExecutor instanceof SingleThreadEventLoop) { - pendingTaskNum += ((SingleThreadEventLoop) eventExecutor).pendingTasks(); - } - } - LOGGER.debug("Parent and child event loop group pending task num {}", pendingTaskNum); - - pendingTaskNum += GlobalEventExecutor.INSTANCE.pendingTasks(); - - LOGGER.debug("Parent and child and global event loop group pending task num {}", pendingTaskNum); - } catch (Throwable e) { - LOGGER.warn("Calculate netty pending task count failed, caused by ", e); - } - - LOGGER.info("Netty pending tasks num is {}", pendingTaskNum); - return pendingTaskNum; - } - - public void setThreadFactory(ThreadFactory threadFactory) { - this.threadFactory = threadFactory; - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/RpcHandler.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/RpcHandler.java deleted file mode 100644 index 355c0329..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/netty/RpcHandler.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.extension.ExtensionLoader; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.model.ShuttingDownEvent; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.rpc.LocalContext; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.Peer; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.ThreadLocalChannelContext; -import com.baidu.cloud.starlight.protocol.stargate.StargateProtocol; -import com.baidu.cloud.starlight.transport.channel.LongRpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandler; -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandlerContext; -import com.baidu.cloud.thirdparty.netty.channel.SimpleChannelInboundHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetSocketAddress; - -/** - * Client Side: Handler Response Server Side: Handler Request Created by liuruisen on 2020/2/3. - */ -@ChannelHandler.Sharable -public class RpcHandler extends SimpleChannelInboundHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(RpcHandler.class); - - private final Peer peer; - - public RpcHandler(Peer peer) { - this.peer = peer; - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - Channel channel = ctx.channel(); - ChannelAttribute attribute = channel.attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute == null && peer instanceof ServerPeer) { // server side - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.SERVER); - // cache channels - ((ServerPeer) peer).rpcChannels().put(toAddressString((InetSocketAddress) channel.remoteAddress()), - rpcChannel); - } - super.channelActive(ctx); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, MsgBase msg) throws Exception { - if (msg == null) { // request or response - throw new StarlightRpcException(StarlightRpcException.MSG_NULL_EXCEPTION, - "The Message read from socket is null"); - } - - ChannelAttribute attribute = ctx.channel().attr(RpcChannel.ATTRIBUTE_KEY).get(); - // set feign rpc channel - if (attribute == null || attribute.getRpcChannel() == null) { // server side - throw new TransportException(TransportException.RPC_CHANNEL_NULL_EXCEPTION, - "RpcChannel in Channel is null"); - } - RpcChannel rpcChannel = attribute.getRpcChannel(); - rpcChannel.receive(msg); // Customized processing - - // client side: handle server SHUTTING_DOWN event - if (msg instanceof Response && peer instanceof ClientPeer) { - RpcResponse response = (RpcResponse) msg; - if (response.getResult() instanceof ShuttingDownEvent) { - LOGGER.info( - "Client receive server shutting down event, will close the related client, " + "remoteAddress {}", - rpcChannel.getRemoteAddress()); - peer.updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, System.currentTimeMillis())); - return; - } - } - - // server side: server is shutting down return shutting down response - if ((peer.status().getStatus().equals(PeerStatus.Status.SHUTTING_DOWN) - || peer.status().getStatus().equals(PeerStatus.Status.SHUTDOWN)) && msg instanceof Request - && peer instanceof ServerPeer) { - LOGGER.warn( - "The server was shutting down and received a request, " + "status {}, remoteAddress {}, request {}", - peer.status(), ctx.channel().remoteAddress(), msg); - RpcResponse shuttingDownResponse = peer.shuttingDownResponse((Request) msg); - Protocol protocol = - ExtensionLoader.getInstance(Protocol.class).getExtension(StargateProtocol.PROTOCOL_NAME); - protocol.getEncoder().encodeBody(shuttingDownResponse); - - ctx.channel().writeAndFlush(shuttingDownResponse); - return; - } - - peer.getProcessor().process(msg, rpcChannel); - } - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its end of - * lifetime. - * - * @param ctx - * @throws Exception - */ - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - Channel channel = ctx.channel(); - - if (peer instanceof ServerPeer) { - LOGGER.info("Server Channel is closing, channelId {}, remoteAddress {}", channel.id().asLongText(), - channel.remoteAddress()); - // remove cached channel - ((ServerPeer) peer).rpcChannels().remove(toAddressString((InetSocketAddress) channel.remoteAddress())); - return; - } - - boolean isHeartbeatFail = false; - if (channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() != null - && channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() >= Constants.MAX_HEARTBEAT_TIMES_VALUE) { - isHeartbeatFail = true; - } - // channel inactive because heartbeat fail will be reconnected through HeartbeatHandler, - // so we do not reconnect here - if (isHeartbeatFail) { - LOGGER.info( - "Client Channel is closing because heartbeat fail, will reconnect. " + "ChannelId {}, remoteAddress {}", - channel.id().asLongText(), channel.remoteAddress()); - return; - } - - ChannelAttribute attribute = channel.attr(RpcChannel.ATTRIBUTE_KEY).get(); - if (attribute != null && attribute.getRpcChannel() != null) { - LOGGER.info( - "Client Channel is being closing may cause by starlight call close " - + "| network unhealth | server closing. " + "ChannelId {}, remoteAddress {}", - channel.id().asLongText(), channel.remoteAddress()); - // fixme Whether to reconnect - // attribute.getRpcChannel().reconnect(); - - if (peer instanceof ClientPeer) { - // 当连接关闭的时候,需要通知一下SSEClientCallBack - RpcCallback sseCallBack = - (RpcCallback) attribute.getRpcChannel().getAttribute(Constants.SSE_CALLBACK_ATTR_KEY); - if (sseCallBack != null) { - sseCallBack.onError(new TransportException("Channel inactive")); - } - } - } - - // remove old channel related classloader from LocalContext - LocalContext.getContext(Constants.LOCAL_CONTEXT_THREAD_CLASSLOADER_KEY).set(channel.id().asLongText(), null); - // super.channelInactive(ctx); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - // FIXME 如何正确处理编解码阶段抛出的异常,最好可以被client端感知 - // super.exceptionCaught(ctx, cause); - LOGGER.debug("NettyHandlers unhandled exception appear, please pay attention. cause by {}", cause.getMessage()); - } - - private String toAddressString(InetSocketAddress address) { - return address.getAddress().getHostAddress() + ":" + address.getPort(); - } -} diff --git a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/utils/TimerHolder.java b/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/utils/TimerHolder.java deleted file mode 100644 index c1f3b957..00000000 --- a/starlight/starlight-transport/src/main/java/com/baidu/cloud/starlight/transport/utils/TimerHolder.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.utils; - -import com.baidu.cloud.starlight.api.rpc.threadpool.NamedThreadFactory; -import com.baidu.cloud.thirdparty.netty.util.HashedWheelTimer; -import com.baidu.cloud.thirdparty.netty.util.Timer; - -/** - * Created by liuruisen on 2020/2/13. - */ -public class TimerHolder { - - /* - * static { Runtime.getRuntime().addShutdownHook(new Thread() { - * - * @Override public void run() { DEFAULT_TIMER.stop(); } }); } - */ - - private static final Timer DEFAULT_TIMER = new HashedWheelTimer(new NamedThreadFactory("Timer")); - - private TimerHolder() { - - } - - public static Timer getTimer() { - return DEFAULT_TIMER; - } -} diff --git a/starlight/starlight-transport/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.transport.TransportFactory b/starlight/starlight-transport/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.transport.TransportFactory deleted file mode 100644 index 6640425a..00000000 --- a/starlight/starlight-transport/src/main/resources/META-INF/services/com.baidu.cloud.starlight.api.transport.TransportFactory +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.transport.StarlightTransportFactory \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/StarlightTransportFactoryTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/StarlightTransportFactoryTest.java deleted file mode 100644 index 242b8813..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/StarlightTransportFactoryTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.transport.ClientPeer; -import com.baidu.cloud.starlight.api.transport.ServerPeer; -import com.baidu.cloud.starlight.transport.netty.NettyClient; -import com.baidu.cloud.starlight.transport.netty.NettyServer; -import org.junit.Assert; -import org.junit.Test; - -/** - * Created by liuruisen on 2020/3/19. - */ -public class StarlightTransportFactoryTest { - - private StarlightTransportFactory transportFactory = new StarlightTransportFactory(); - - @Test - public void client() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8888); - ClientPeer peer = transportFactory.client(builder.build()); - Assert.assertTrue(peer instanceof NettyClient); - } - - @Test - public void server() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8888); - ServerPeer peer = transportFactory.server(builder.build()); - Assert.assertTrue(peer instanceof NettyServer); - - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactoryTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactoryTest.java deleted file mode 100644 index f6f04823..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/ChannelPooledObjectFactoryTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.pool2.PooledObject; -import com.baidu.cloud.thirdparty.pool2.impl.DefaultPooledObject; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - -/** - * Created by liuruisen on 2020/8/24. - */ -public class ChannelPooledObjectFactoryTest { - - @Test - public void validateObject() { - ChannelPooledObjectFactory factory = new ChannelPooledObjectFactory( - new PooledRpcChannelGroup(new URI.Builder("brpc://localhost:8999").build(), new Bootstrap())); - RpcChannel mockChannel = Mockito.mock(RpcChannel.class); - when(mockChannel.isActive()).thenReturn(true); - PooledObject pooledObject = new DefaultPooledObject(mockChannel); - assertTrue(factory.validateObject(pooledObject)); - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannelTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannelTest.java deleted file mode 100644 index 19d6eb33..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/LongRpcChannelTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.AbstractMsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelId; -import com.baidu.cloud.thirdparty.netty.channel.DefaultChannelId; -import com.baidu.cloud.thirdparty.netty.util.Attribute; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class LongRpcChannelTest { - - private Bootstrap bootstrap; - - private URI uri; - - private LongRpcChannel rpcChannel; - - private Channel channel; - - @Before - public void before() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - uri = builder.build(); - - bootstrap = Mockito.mock(Bootstrap.class); - - ChannelFuture channelFuture = Mockito.mock(ChannelFuture.class); - doReturn(true).when(channelFuture).awaitUninterruptibly(ArgumentMatchers.anyLong()); - doReturn(true).when(channelFuture).isSuccess(); - - doReturn(channelFuture).when(bootstrap).connect(any()); - - channel = Mockito.mock(Channel.class); - doReturn(channel).when(channelFuture).channel(); - - ChannelId channelId = DefaultChannelId.newInstance(); - Attribute attribute = Mockito.mock(Attribute.class); - doReturn(attribute).when(channel).attr(any()); - doReturn(channelId).when(channel).id(); - doNothing().when(attribute).set(any()); - doReturn(channelFuture).when(channel).close(); - doReturn(true).when(channel).isActive(); - doReturn(channelFuture).when(channel).writeAndFlush(any()); - - rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - } - - @Test - public void init() { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - rpcChannel.init(); - Channel channel = rpcChannel.channel(); - Assert.assertTrue(channel.isActive()); - rpcChannel.init(); - Assert.assertEquals(channel, rpcChannel.channel()); - } - - @Test - public void isActive() { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - assertTrue(rpcChannel.isActive()); - rpcChannel.close(); - assertFalse(rpcChannel.isActive()); - } - - @Test - public void reconnect() { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - rpcChannel.reconnect(); - Channel channel = rpcChannel.channel(); - Assert.assertTrue(channel.isActive()); - } - - @Test - public void channel() { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - rpcChannel.channel(); - Assert.assertTrue(channel.isActive()); - } - - @Test - public void close() throws IllegalAccessException, NoSuchFieldException { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - - new Thread(() -> { - rpcChannel.putCallback(1L, new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) { - - } - - @Override - public Request getRequest() { - return null; - } - - @Override - public void onResponse(Response response) { - - } - - @Override - public void onError(Throwable e) { - - } - }); - - try { - TimeUnit.SECONDS.sleep(20); // Simulate request processing - } catch (InterruptedException e) { - // ignore - } - rpcChannel.removeCallback(1L); - }).start(); - - try { - TimeUnit.MILLISECONDS.sleep(100); - } catch (InterruptedException e) { - // ignore - } - - assertEquals(1, rpcChannel.allCallbacks().size()); - assertTrue(rpcChannel.isActive()); - - rpcChannel.close(); - - assertEquals(0, rpcChannel.allCallbacks().size()); - assertFalse(rpcChannel.isActive()); - - Field field = rpcChannel.getClass().getDeclaredField("channel"); - field.setAccessible(true); - - Assert.assertNotNull(field.get(rpcChannel)); - } - - @Test - public void send() { - RpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - rpcChannel.send(new RpcRequest()); - } - - @Test - public void sendError() { - Bootstrap bootstrap = Mockito.mock(Bootstrap.class); - - ChannelFuture connectFuture = Mockito.mock(ChannelFuture.class); - doReturn(true).when(connectFuture).awaitUninterruptibly(ArgumentMatchers.anyLong()); - doReturn(true).when(connectFuture).isSuccess(); - - doReturn(connectFuture).when(bootstrap).connect(any()); - - Channel channel = Mockito.mock(Channel.class); - ChannelId channelId = DefaultChannelId.newInstance(); - doReturn(channel).when(connectFuture).channel(); - doReturn(true).when(channel).isActive(); - Attribute attribute = Mockito.mock(Attribute.class); - doReturn(attribute).when(channel).attr(any()); - doReturn(channelId).when(channel).id(); - doNothing().when(attribute).set(any()); - - ChannelFuture writeFuture = Mockito.mock(ChannelFuture.class); - doReturn(true).when(writeFuture).awaitUninterruptibly(ArgumentMatchers.anyLong()); - doReturn(false).when(writeFuture).isSuccess(); - - doReturn(writeFuture).when(channel).writeAndFlush(any()); - - RpcChannel longChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - // channel is not active - try { - longChannel.send(new RpcRequest()); - } catch (TransportException e) { - Assert.assertEquals(e.getMessage(), "Remote Channel is inactive"); - } - - doReturn(true).when(channel).isActive(); - Exception exception = new Exception("Test"); - doReturn(exception).when(writeFuture).cause(); - // send fail - try { - longChannel.send(new AbstractMsgBase() {}); - } catch (TransportException e) { - Assert.assertEquals(e.getCode(), TransportException.WRITE_EXCEPTION); - } - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroupTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroupTest.java deleted file mode 100644 index 2ff55796..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/channel/SingleRpcChannelGroupTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.channel; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelId; -import com.baidu.cloud.thirdparty.netty.channel.DefaultChannelId; -import com.baidu.cloud.thirdparty.netty.util.Attribute; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/12/7. - */ -public class SingleRpcChannelGroupTest { - - private URI uri; - - private Bootstrap bootstrap; - - @Before - public void before() { - String baseUriString = "brpc://admin:hello1234@10.20.30.40:20880/context/path?app=mail"; - uri = URI.valueOf(baseUriString); - - bootstrap = Mockito.mock(Bootstrap.class); - - ChannelFuture channelFuture = Mockito.mock(ChannelFuture.class); - doReturn(true).when(channelFuture).awaitUninterruptibly(ArgumentMatchers.anyLong()); - doReturn(true).when(channelFuture).isSuccess(); - - doReturn(channelFuture).when(bootstrap).connect(any()); - - Channel channel = Mockito.mock(Channel.class); - doReturn(channel).when(channelFuture).channel(); - - ChannelId channelId = DefaultChannelId.newInstance(); - Attribute attribute = Mockito.mock(Attribute.class); - doReturn(attribute).when(channel).attr(any()); - doReturn(channelId).when(channel).id(); - doNothing().when(attribute).set(any()); - doReturn(channelFuture).when(channel).close(); - doReturn(true).when(channel).isActive(); - doReturn(channelFuture).when(channel).writeAndFlush(any()); - } - - @Test - public void getRpcChannel() { - SingleRpcChannelGroup singleRpcChannelGroup = new SingleRpcChannelGroup(uri, bootstrap); - singleRpcChannelGroup.init(); - RpcChannel rpcChannel = singleRpcChannelGroup.getRpcChannel(); - assertNotNull(rpcChannel); - - // mock request 1 - new Thread(() -> { - rpcChannel.putCallback(1L, new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) {} - - @Override - public Request getRequest() { - return null; - } - - @Override - public void onResponse(Response response) {} - - @Override - public void onError(Throwable e) {} - }); - - try { - TimeUnit.SECONDS.sleep(30); // Simulate request processing - } catch (InterruptedException e) { - // ignore - } - rpcChannel.removeCallback(1L); - }).start(); - - try { - TimeUnit.MILLISECONDS.sleep(200); - } catch (InterruptedException e) { - // ignore - } - assertEquals(1, rpcChannel.allCallbacks().size()); - - // mock disconnect cause by heartbeat fail - singleRpcChannelGroup.removeRpcChannel(rpcChannel); - // wait for reconnect task exec - try { - TimeUnit.MILLISECONDS.sleep(200); - } catch (InterruptedException e) { - // ignore - } - - // mock request 2 - RpcChannel rpcChannel2 = singleRpcChannelGroup.getRpcChannel(); - assertNotNull(rpcChannel2); - assertTrue(rpcChannel != rpcChannel2); - - // another request - new Thread(() -> { - rpcChannel2.putCallback(2L, new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) {} - - @Override - public Request getRequest() { - return null; - } - - @Override - public void onResponse(Response response) {} - - @Override - public void onError(Throwable e) {} - }); - - try { - TimeUnit.SECONDS.sleep(3); // Simulate request processing - } catch (InterruptedException e) { - // ignore - } - rpcChannel.removeCallback(1L); - }).start(); - - try { - TimeUnit.MILLISECONDS.sleep(200); - } catch (InterruptedException e) { - // ignore - } - - // wait for old channel close - try { - TimeUnit.SECONDS.sleep(40); - } catch (InterruptedException e) { - // ignore - } - - assertEquals(0, rpcChannel.allCallbacks().size()); - } - - @Test - public void rpcChannelCount() { - SingleRpcChannelGroup singleRpcChannelGroup = new SingleRpcChannelGroup(uri, bootstrap); - assertEquals(1, singleRpcChannelGroup.rpcChannelCount()); - } - - @Test - public void allRpcChannels() { - SingleRpcChannelGroup singleRpcChannelGroup = new SingleRpcChannelGroup(uri, bootstrap); - assertEquals(1, singleRpcChannelGroup.allRpcChannels().size()); - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/CustomEmbeddedChannel.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/CustomEmbeddedChannel.java deleted file mode 100644 index 74690f9e..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/CustomEmbeddedChannel.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.thirdparty.netty.channel.ChannelHandler; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -/** - * Created by liuruisen on 2021/1/8. - */ -public class CustomEmbeddedChannel extends EmbeddedChannel { - - private InetSocketAddress socketAddress; - - public CustomEmbeddedChannel(String host, int port, final ChannelHandler... handlers) { - super(handlers); - socketAddress = new InetSocketAddress(host, port); - } - - @Override - protected SocketAddress remoteAddress0() { - return this.socketAddress; - } -} diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/DecoderHandlerTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/DecoderHandlerTest.java deleted file mode 100644 index 28c5a6a5..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/DecoderHandlerTest.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.protocol.http.springrest.sse.SpringRestSseProtocol; -import com.baidu.cloud.starlight.transport.channel.LongRpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.protocol.brpc.BrpcEncoder; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.CompositeByteBuf; -import com.baidu.cloud.thirdparty.netty.buffer.Unpooled; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultFullHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpContent; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.DefaultHttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpHeaderNames; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpObject; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponse; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseEncoder; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpResponseStatus; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.HttpVersion; -import com.baidu.cloud.thirdparty.netty.handler.codec.http.LastHttpContent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class DecoderHandlerTest { - - private ByteBuf requestBuf = null; - - @Before - public void init() { - Map kvMap = new HashMap<>(); - kvMap.put(Constants.TRACE_ID_KEY, 123l); - kvMap.put(Constants.SPAN_ID_KEY, 2l); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, 1l); - kvMap.put("Key1", "Value1"); - - BrpcEncoder brpcEncoder = new BrpcEncoder(); - - RpcRequest rpcRequest = new RpcRequest(); - rpcRequest.setMethodName("init"); - rpcRequest.setServiceClass(this.getClass()); - rpcRequest.setServiceConfig(new ServiceConfig()); - rpcRequest.setParams(new Object[] {"Test"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - rpcRequest.setProtocolName("brpc"); - rpcRequest.setAttachmentKv(kvMap); - - brpcEncoder.encodeBody(rpcRequest); - requestBuf = brpcEncoder.encode(rpcRequest); - } - - @Test - public void decodeKnowProtocol() { - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - - // none rpcChannel attr in Channel - try { - channel.writeInbound(requestBuf.retain()); - } catch (Exception e) { - Assert.assertTrue(e instanceof TransportException); - } - - // set know protocol rpcChannel - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.SERVER); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - // know protocol decode - channel.writeInbound(requestBuf.retain()); - RpcRequest rpcRequest = channel.readInbound(); - Assert.assertTrue(rpcRequest.getServiceName().equals(this.getClass().getName())); - } - - @Test - public void decodeUnKnowProtocol() { - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - - // set unKnow protocol rpcChannel - URI.Builder builder2 = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, "localhost", 8006); - LongRpcChannel rpcChannel2 = new LongRpcChannel(channel, ChannelSide.SERVER); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel2); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - // unKnow protocol rpcChannel - channel.writeInbound(requestBuf.retain()); - RpcRequest rpcRequest1 = channel.readInbound(); - Assert.assertTrue(rpcRequest1.getServiceName().equals(this.getClass().getName())); - Assert.assertTrue(attribute.getChannelProtocol().equals("brpc")); - } - - @Test - public void decodeUnCorrectProtocol() { - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - - // set un correct, request is brpc but uri protocol is atest - URI.Builder builder2 = new URI.Builder("atest", "localhost", 8006); - LongRpcChannel rpcChannel2 = new LongRpcChannel(channel, ChannelSide.SERVER); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel2); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - // unKnow protocol - channel.writeInbound(requestBuf.retain()); - RpcRequest rpcRequest = channel.readInbound(); - Assert.assertTrue(rpcRequest.getServiceName().equals(this.getClass().getName())); - Assert.assertTrue(attribute.getChannelProtocol().equals("brpc")); - } - - @Test - public void decodeUnSpecificProtocol() { - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - - // set unKnow protocol rpcChannel - URI.Builder builder2 = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, "localhost", 8006); - LongRpcChannel rpcChannel2 = new LongRpcChannel(channel, ChannelSide.SERVER); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel2); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - // unKnow protocol rpcChannel - channel.writeInbound(requestBuf.retain()); - RpcRequest rpcRequest = channel.readInbound(); - Assert.assertTrue(rpcRequest.getServiceName().equals(this.getClass().getName())); - Assert.assertTrue(attribute.getChannelProtocol().equals("brpc")); - } - - @Test - public void decodeErrorMsg() { - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - - URI.Builder builder2 = new URI.Builder(Constants.UNSPECIFIED_PROTOCOL, "localhost", 8006); - LongRpcChannel rpcChannel2 = new LongRpcChannel(channel, ChannelSide.SERVER); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel2)); - try { - // InSufficient msg - ByteBuf byteBuf = Unpooled.wrappedBuffer("1".getBytes()); - channel.writeInbound(byteBuf); - } catch (Exception e) { - Assert.assertNotNull(e); - } - - try { - // error msg - ByteBuf byteBuf = Unpooled.wrappedBuffer("12345678901234567890".getBytes()); - channel.writeInbound(byteBuf); - } catch (Exception e) { - Assert.assertNotNull(e); - } - } - - @Ignore - @Test - public void testDecodeHttpProtocol() { - - // 模拟 半个response数据包 - ByteBuf data1 = Unpooled.wrappedBuffer("response1".getBytes(StandardCharsets.UTF_8)); - DefaultFullHttpResponse response1 = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, data1); - response1.headers().add("Content-Length", data1.readableBytes()); - - EmbeddedChannel outboundChannel = new EmbeddedChannel(new HttpResponseEncoder()); - outboundChannel.writeOutbound(response1); - - CompositeByteBuf outboundByteBuf = Unpooled.compositeBuffer(); - for (Object msg : outboundChannel.outboundMessages()) { - outboundByteBuf.addComponent(true, (ByteBuf) msg); - } - - int half = outboundByteBuf.readableBytes() / 2; - // 前半个 - ByteBuf halfOutboundByteBuf = outboundByteBuf.slice(0, half); - // 后半个 - ByteBuf restOutboundByteBuf = outboundByteBuf.slice(half, outboundByteBuf.readableBytes() - half); - // -- 模拟完毕 - - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.SERVER); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - - try { - // 收到一个包被拆包的情况,第一次就会失败 - channel.writeInbound(halfOutboundByteBuf); - } catch (Exception e) { - System.out.println("ignore1:" + e.getMessage()); - } - - // 收到第二个包的时候,包就完整了,就不会报错了 - channel.writeInbound(restOutboundByteBuf); - - // 最终能 decode 出一个完整的Response包 - RpcResponse rpcResponse = channel.readInbound(); - Assert.assertNotNull(rpcResponse); - - } - - @Test - public void testDecodeSSEResponse() { - - // 模拟多个sse response数据包 - EmbeddedChannel outboundChannel = new EmbeddedChannel(new HttpResponseEncoder()); - - HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/event-stream"); - response.headers().set(HttpHeaderNames.CACHE_CONTROL, "no-cache"); - response.headers().set(HttpHeaderNames.CONNECTION, "keep-alive"); - response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "chunked"); - - outboundChannel.writeOutbound(response); - - for (int i = 0; i < 5; i++) { - String eventData = "data: Event from server\n\n"; - - ByteBuf content = Unpooled.copiedBuffer(eventData, StandardCharsets.UTF_8); - DefaultHttpContent httpContent = new DefaultHttpContent(content); - outboundChannel.writeOutbound(httpContent); - } - - outboundChannel.writeOutbound(LastHttpContent.EMPTY_LAST_CONTENT); - - CompositeByteBuf outboundByteBuf = Unpooled.compositeBuffer(); - for (Object msg : outboundChannel.outboundMessages()) { - outboundByteBuf.addComponent(true, (ByteBuf) msg); - } - - // 把数据分为 多份 - int count = 5; - - if (outboundByteBuf.readableBytes() < count) { - // 如果不够分 ,则不能进行这个测试 - System.out.println("[WARN] data not enough"); - return; - } - - int size_per_count = outboundByteBuf.readableBytes() / count; - - List byteBufList = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - if (i == count - 1) { - // 最后一份 取剩下所有的 - byteBufList.add( - outboundByteBuf.copy(i * size_per_count, outboundByteBuf.readableBytes() - i * size_per_count)); - } else { - byteBufList.add(outboundByteBuf.copy(i * size_per_count, size_per_count)); - } - } - // -- 模拟完毕 - - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - ChannelAttribute channelAttribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(channelAttribute); - channelAttribute.resetChannelProtocol(SpringRestSseProtocol.PROTOCOL_NAME); - - for (ByteBuf partByteBuf : byteBufList) { - try { - channel.writeInbound(partByteBuf); - } catch (Exception e) { - System.out.println("ignore:" + e.getMessage()); - } - } - - List messages = - channel.inboundMessages().stream().map(o -> (Response) o).collect(Collectors.toList()); - - List httpObjects = messages.stream().flatMap(resp -> ((List) resp.getResult()).stream()) - .collect(Collectors.toList()); - - Assert.assertEquals(httpObjects.size(), 2); - } - - @Test - public void testDecodeSSEResponse2() { - - // 模拟多个sse response数据包 & 错误请求 - EmbeddedChannel outboundChannel = new EmbeddedChannel(new HttpResponseEncoder()); - - HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.SERVICE_UNAVAILABLE); - response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/event-stream"); - response.headers().set(HttpHeaderNames.CACHE_CONTROL, "no-cache"); - response.headers().set(HttpHeaderNames.CONNECTION, "keep-alive"); - response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "chunked"); - - outboundChannel.writeOutbound(response); - - for (int i = 0; i < 5; i++) { - String eventData = "data: Event from server\n\n"; - - ByteBuf content = Unpooled.copiedBuffer(eventData, StandardCharsets.UTF_8); - DefaultHttpContent httpContent = new DefaultHttpContent(content); - outboundChannel.writeOutbound(httpContent); - } - - outboundChannel.writeOutbound(LastHttpContent.EMPTY_LAST_CONTENT); - - CompositeByteBuf outboundByteBuf = Unpooled.compositeBuffer(); - for (Object msg : outboundChannel.outboundMessages()) { - outboundByteBuf.addComponent(true, (ByteBuf) msg); - } - - // 把数据分为 多份 - int count = 5; - - if (outboundByteBuf.readableBytes() < count) { - // 如果不够分 ,则不能进行这个测试 - System.out.println("[WARN] data not enough"); - return; - } - - int size_per_count = outboundByteBuf.readableBytes() / count; - - List byteBufList = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - if (i == count - 1) { - // 最后一份 取剩下所有的 - byteBufList.add( - outboundByteBuf.copy(i * size_per_count, outboundByteBuf.readableBytes() - i * size_per_count)); - } else { - byteBufList.add(outboundByteBuf.copy(i * size_per_count, size_per_count)); - } - } - // -- 模拟完毕 - - EmbeddedChannel channel = new CustomEmbeddedChannel("localhost", 8006, new DecoderHandler()); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - ChannelAttribute channelAttribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(channelAttribute); - channelAttribute.resetChannelProtocol(SpringRestSseProtocol.PROTOCOL_NAME); - - for (ByteBuf partByteBuf : byteBufList) { - try { - channel.writeInbound(partByteBuf); - } catch (Exception e) { - System.out.println("ignore:" + e.getMessage()); - } - } - - List messages = - channel.inboundMessages().stream().map(o -> (Response) o).collect(Collectors.toList()); - - List httpObjects = messages.stream().flatMap(resp -> ((List) resp.getResult()).stream()) - .collect(Collectors.toList()); - - Assert.assertEquals(httpObjects.size(), 0); - } - -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/EncoderHandlerTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/EncoderHandlerTest.java deleted file mode 100644 index 5ad1ce9b..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/EncoderHandlerTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.AbstractMsgBase; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.transport.channel.LongRpcChannel; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class EncoderHandlerTest { - - private RpcRequest rpcRequest; - - @Before - public void init() { - Map kvMap = new HashMap<>(); - kvMap.put(Constants.TRACE_ID_KEY, 123l); - kvMap.put(Constants.SPAN_ID_KEY, 2l); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, 1l); - kvMap.put("Key1", "Value1"); - rpcRequest = new RpcRequest(); - rpcRequest.setMethodName("init"); - rpcRequest.setServiceClass(this.getClass()); - rpcRequest.setServiceConfig(new ServiceConfig()); - rpcRequest.setParams(new Object[] {"Test"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - rpcRequest.setProtocolName("brpc"); - rpcRequest.setAttachmentKv(kvMap); - } - - @Test - public void encode() { - EmbeddedChannel channel = new EmbeddedChannel(new EncoderHandler()); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - - channel.writeOutbound(rpcRequest); - ByteBuf byteBuf = channel.readOutbound(); - Assert.assertTrue(byteBuf.readableBytes() > 0); - } - - @Test(expected = Exception.class) - public void encodeErrorMsg() { - EmbeddedChannel channel = new EmbeddedChannel(new EncoderHandler()); - - // encode null protocol - rpcRequest.setProtocolName(null); - channel.writeOutbound(rpcRequest); - - // encode null protocol - MsgBase msgBase = new AbstractMsgBase() {}; - msgBase.setProtocolName("brpc"); - channel.writeOutbound(msgBase); - } - -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandlerTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandlerTest.java deleted file mode 100644 index 0ea9f6e8..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/HeartbeatHandlerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.transport.channel.LongRpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.transport.protocol.test.ATestProtocol; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import com.baidu.cloud.thirdparty.netty.handler.timeout.IdleStateHandler; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.util.concurrent.TimeUnit; - -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class HeartbeatHandlerTest { - - /** - * Test heartbeat trigger when Protocol not support heartbeat msg - * - * @throws Exception - */ - @Test - public void clientHeartbeatEventProtocolNotSupport() throws Exception { - IdleStateHandler idleStateHandler = new IdleStateHandler(1L, 0L, 0L, TimeUnit.SECONDS); - - EmbeddedChannel channel = new EmbeddedChannel(idleStateHandler, new HeartbeatHandler()); - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doReturn(channel).when(rpcChannel).channel(); - doReturn(ChannelSide.CLIENT).when(rpcChannel).side(); - doReturn("brpc").when(rpcChannel).getAttribute(Constants.PROTOCOL_ATTR_KEY); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - - TimeUnit.SECONDS.sleep(2); - channel.runPendingTasks(); - - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() > 0); - - channel.finish(); - } - - /** - * Test heartbeat trigger when Protocol support heartbeat msg - * - * @throws Exception - */ - @Test - public void clientHeartbeatEventProtocolSupport() throws Exception { - IdleStateHandler idleStateHandler = new IdleStateHandler(1L, 0L, 0L, TimeUnit.SECONDS); - EmbeddedChannel channel = new EmbeddedChannel(idleStateHandler, new HeartbeatHandler()); - - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doReturn(channel).when(rpcChannel).channel(); - doReturn(ChannelSide.CLIENT).when(rpcChannel).side(); - ChannelAttribute attribute = new ChannelAttribute(rpcChannel); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(attribute); - - TimeUnit.SECONDS.sleep(2); - channel.runPendingTasks(); - - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() >= 1); - - channel.finish(); - } - - @Test - public void serverHeartbeatEvent() throws Exception { - - IdleStateHandler idleStateHandler = new IdleStateHandler(0L, 0L, 1L, TimeUnit.SECONDS); - - EmbeddedChannel channel = new EmbeddedChannel(idleStateHandler, new HeartbeatHandler()); - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doReturn(channel).when(rpcChannel).channel(); - doReturn(ChannelSide.SERVER).when(rpcChannel).side(); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - - TimeUnit.SECONDS.sleep(2); - channel.runPendingTasks(); - - Assert.assertFalse(channel.isActive()); - - channel.finish(); - - } - - @Test - public void clientHeartbeatRead() { - URI.Builder builder = new URI.Builder("atest", "localhost", 8006); - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doNothing().when(rpcChannel).send(ArgumentMatchers.any()); - - EmbeddedChannel channel = new EmbeddedChannel(new HeartbeatHandler()); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - ATestProtocol testProtocol = new ATestProtocol(); - Response response = testProtocol.getHeartbeatTrigger().heartbeatResponse(); - - channel.writeInbound(response); - - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() == 0); - Response response2 = channel.readInbound(); - Assert.assertTrue(response2 == null); - - channel.finish(); - } - - @Test - public void serverHeartbeatRead() { - URI.Builder builder = new URI.Builder("atest", "localhost", 8006); - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doNothing().when(rpcChannel).send(ArgumentMatchers.any()); - - EmbeddedChannel channel = new EmbeddedChannel(new HeartbeatHandler()); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - ATestProtocol testProtocol = new ATestProtocol(); - Request request = testProtocol.getHeartbeatTrigger().heartbeatRequest(); - - channel.writeInbound(request); - - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() == 0); - Request request2 = channel.readInbound(); - Assert.assertTrue(request2 == null); - - channel.finish(); - } - - @Test - public void normalMsgRead() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - LongRpcChannel rpcChannel = Mockito.mock(LongRpcChannel.class); - doNothing().when(rpcChannel).reconnect(); - doNothing().when(rpcChannel).send(ArgumentMatchers.any()); - - EmbeddedChannel channel = new EmbeddedChannel(new HeartbeatHandler()); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - - channel.writeInbound(new RpcResponse()); - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() == 0); - - channel.writeInbound("Test"); - Assert.assertTrue(channel.attr(HeartbeatHandler.HEARTBEAT_FAIL_TIMES).get() == 0); - - channel.finish(); - } - -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyClientTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyClientTest.java deleted file mode 100644 index 9551ea1b..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyClientTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.StarlightRpcException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.callback.RpcCallback; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.PeerStatus; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannelGroup; -import com.baidu.cloud.thirdparty.netty.bootstrap.Bootstrap; -import com.baidu.cloud.thirdparty.netty.channel.Channel; -import com.baidu.cloud.thirdparty.netty.channel.ChannelFuture; -import com.baidu.cloud.thirdparty.netty.channel.ChannelId; -import com.baidu.cloud.thirdparty.netty.channel.DefaultChannelId; -import com.baidu.cloud.thirdparty.netty.util.Attribute; -import com.baidu.cloud.thirdparty.netty.util.Timeout; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class NettyClientTest { - - @Test - public void init() throws NoSuchFieldException, IllegalAccessException { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.init(); - Field field = nettyClient.getClass().getDeclaredField("bootstrap"); - field.setAccessible(true); - Bootstrap bootstrap = (Bootstrap) field.get(nettyClient); - Assert.assertTrue(bootstrap != null); - } - - @Test - public void connect() throws NoSuchFieldException, IllegalAccessException { - Bootstrap bootstrap = Mockito.mock(Bootstrap.class); - ChannelFuture channelFuture = Mockito.mock(ChannelFuture.class); - doReturn(channelFuture).when(bootstrap).connect(ArgumentMatchers.any()); - doReturn(true).when(channelFuture).awaitUninterruptibly(ArgumentMatchers.anyLong()); - doReturn(true).when(channelFuture).isSuccess(); - Channel channel = Mockito.mock(Channel.class); - doReturn(channel).when(channelFuture).channel(); - Attribute attribute = Mockito.mock(Attribute.class); - doReturn(attribute).when(channel).attr(ArgumentMatchers.any()); - ChannelId channelId = DefaultChannelId.newInstance(); - doReturn(channelId).when(channel).id(); - doNothing().when(attribute).set(ArgumentMatchers.any()); - - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.init(); - Field field = nettyClient.getClass().getDeclaredField("bootstrap"); - field.setAccessible(true); - field.set(nettyClient, bootstrap); - - nettyClient.connect(); - - RpcChannelGroup rpcChannelGroup = nettyClient.getChannelGroup(); - Assert.assertTrue(rpcChannelGroup != null); - Assert.assertTrue(rpcChannelGroup.getUri().getProtocol().equals("brpc")); - } - - @Test - public void request() throws NoSuchFieldException, IllegalAccessException { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - - RpcChannel rpcChannel = Mockito.mock(RpcChannel.class); - doNothing().when(rpcChannel).putCallback(ArgumentMatchers.anyLong(), ArgumentMatchers.any()); - doNothing().when(rpcChannel).send(ArgumentMatchers.any()); - - RpcChannelGroup channelGroup = Mockito.mock(RpcChannelGroup.class); - doReturn(rpcChannel).when(channelGroup).getRpcChannel(); - Field field = nettyClient.getClass().getDeclaredField("rpcChannelGroup"); - field.setAccessible(true); - field.set(nettyClient, channelGroup); - nettyClient.request(new RpcRequest(), new RpcCallback() { - @Override - public void addTimeout(Timeout timeout) { - - } - - @Override - public Request getRequest() { - return null; - } - - @Override - public void onResponse(Response response) { - - } - - @Override - public void onError(Throwable e) { - - } - }); - - } - - @Test - public void getUri() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - URI uri = nettyClient.getUri(); - Assert.assertTrue(uri.getPort() == 8006); - } - - @Test - public void closeNull() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.close(); - } - - @Test - public void close() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.setProcessor(new Processor() { - @Override - public ServiceRegistry getRegistry() { - return null; - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - } - - @Override - public void close() { - - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - - } - - @Override - public Integer waitTaskCount(String serviceKey) { - return null; - } - - @Override - public Integer processingCount(String serviceKey) { - return null; - } - - @Override - public Long completeCount(String serviceKey) { - return null; - } - - @Override - public Integer allWaitTaskCount() { - return null; - } - }); - nettyClient.close(); - } - - @Test - public void setProcessor() { - Processor clientProcessor = new Processor() { - @Override - public ServiceRegistry getRegistry() { - return null; - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - } - - @Override - public void close() { - - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - - } - - @Override - public Integer waitTaskCount(String serviceKey) { - return null; - } - - @Override - public Integer processingCount(String serviceKey) { - return null; - } - - @Override - public Long completeCount(String serviceKey) { - return null; - } - - @Override - public Integer allWaitTaskCount() { - return null; - } - }; - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.setProcessor(clientProcessor); - - Assert.assertTrue(nettyClient.getProcessor() == clientProcessor); - } - - @Test - public void rpcChannelGroup() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - - Method method = nettyClient.getClass().getDeclaredMethod("rpcChannelGroup", String.class); - method.setAccessible(true); - - try { - method.invoke(nettyClient, new Object[] {null}); - } catch (Exception e) { - Assert.assertTrue(e.getCause().getMessage().equals("RpcChannelGroup type is null")); - } - - try { - method.invoke(nettyClient, "test"); - } catch (Exception e) { - Assert.assertTrue(e.getCause() instanceof StarlightRpcException); - Assert.assertTrue(e.getCause().getMessage().contains("is illegal: not support")); - } - } - - @Test - public void updateStatus() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.updateStatus(new PeerStatus(PeerStatus.Status.ACTIVE, System.currentTimeMillis())); - - assertEquals(PeerStatus.Status.ACTIVE, nettyClient.status().getStatus()); - } - - @Test - public void updateStatusShuttingDown() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.updateStatus(new PeerStatus(PeerStatus.Status.SHUTTING_DOWN, System.currentTimeMillis())); - assertEquals(PeerStatus.Status.SHUTTING_DOWN, nettyClient.status().getStatus()); - - nettyClient.updateStatus(new PeerStatus(PeerStatus.Status.OUTLIER, System.currentTimeMillis())); - assertEquals(PeerStatus.Status.SHUTTING_DOWN, nettyClient.status().getStatus()); - - nettyClient.updateStatus(new PeerStatus(PeerStatus.Status.SHUTDOWN, System.currentTimeMillis())); - assertEquals(PeerStatus.Status.SHUTDOWN, nettyClient.status().getStatus()); - - nettyClient.updateStatus(new PeerStatus(PeerStatus.Status.OUTLIER, System.currentTimeMillis())); - assertEquals(PeerStatus.Status.SHUTDOWN, nettyClient.status().getStatus()); - } - - @Test - public void updateStatusOutlier() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyClient nettyClient = new NettyClient(builder.build()); - - long outlierTime1 = System.currentTimeMillis(); - PeerStatus peerStatus = new PeerStatus(PeerStatus.Status.OUTLIER, outlierTime1); - nettyClient.updateStatus(peerStatus); - assertEquals(peerStatus, nettyClient.status()); - - PeerStatus peerStatusBefore = new PeerStatus(PeerStatus.Status.OUTLIER, outlierTime1 - 1); - nettyClient.updateStatus(peerStatusBefore); - assertEquals(peerStatus, nettyClient.status()); - - PeerStatus peerStatusAfter = new PeerStatus(PeerStatus.Status.OUTLIER, outlierTime1 + 1); - nettyClient.updateStatus(peerStatusAfter); - assertNotEquals(peerStatusAfter, nettyClient.status()); - - } - -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyServerTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyServerTest.java deleted file mode 100644 index f2306094..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/NettyServerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.bootstrap.ServerBootstrap; -import com.baidu.cloud.thirdparty.netty.channel.ServerChannel; -import org.junit.Assert; -import org.junit.Test; - -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class NettyServerTest { - - @Test - public void init() throws NoSuchFieldException, IllegalAccessException { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyServer nettyServer = new NettyServer(builder.build()); - nettyServer.init(); - Field field = nettyServer.getClass().getDeclaredField("bootstrap"); - field.setAccessible(true); - ServerBootstrap bootstrap = (ServerBootstrap) field.get(nettyServer); - Assert.assertTrue(bootstrap != null); - } - - @Test - public void bindAndClose() throws NoSuchFieldException, IllegalAccessException, InterruptedException { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyServer nettyServer = new NettyServer(builder.build()); - nettyServer.init(); - nettyServer.bind(); - TimeUnit.SECONDS.sleep(1); - - Field field = nettyServer.getClass().getDeclaredField("serverChannel"); - field.setAccessible(true); - ServerChannel channel = (ServerChannel) field.get(nettyServer); - Assert.assertTrue(channel.isActive()); - Assert.assertTrue(nettyServer.isBound()); - - nettyServer.close(); - TimeUnit.SECONDS.sleep(1); - Assert.assertFalse(nettyServer.isBound()); - } - - @Test - public void getUri() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyServer nettyServer = new NettyServer(builder.build()); - Assert.assertTrue(nettyServer.getUri().getPort() == 8006); - } - - @Test - public void setProcessor() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - NettyServer nettyServer = new NettyServer(builder.build()); - nettyServer.setProcessor(new Processor() { - @Override - public ServiceRegistry getRegistry() { - return null; - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - } - - @Override - public void close() { - - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - - } - - @Override - public Integer waitTaskCount(String serviceKey) { - return 0; - } - - @Override - public Integer processingCount(String serviceKey) { - return 0; - } - - @Override - public Long completeCount(String serviceKey) { - return 0l; - } - - @Override - public Integer allWaitTaskCount() { - return 0; - } - }); - Assert.assertTrue(nettyServer.getProcessor() != null); - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/RpcHandlerTest.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/RpcHandlerTest.java deleted file mode 100644 index 0898725f..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/netty/RpcHandlerTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.netty; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.common.URI; -import com.baidu.cloud.starlight.api.exception.TransportException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.rpc.Processor; -import com.baidu.cloud.starlight.api.rpc.RpcService; -import com.baidu.cloud.starlight.api.rpc.ServiceRegistry; -import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig; -import com.baidu.cloud.starlight.api.rpc.threadpool.ThreadPoolFactory; -import com.baidu.cloud.starlight.api.transport.channel.ChannelAttribute; -import com.baidu.cloud.starlight.api.transport.channel.ChannelSide; -import com.baidu.cloud.starlight.transport.channel.LongRpcChannel; -import com.baidu.cloud.starlight.api.transport.channel.RpcChannel; -import com.baidu.cloud.thirdparty.netty.channel.embedded.EmbeddedChannel; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ThreadPoolExecutor; - -import static org.mockito.Mockito.doNothing; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class RpcHandlerTest { - - private RpcRequest rpcRequest; - - private RpcResponse rpcResponse; - - @Before - public void init() { - Map kvMap = new HashMap<>(); - kvMap.put(Constants.TRACE_ID_KEY, 123l); - kvMap.put(Constants.SPAN_ID_KEY, 2l); - kvMap.put(Constants.PARENT_SPAN_ID_KEY, 1l); - kvMap.put("Key1", "Value1"); - - rpcRequest = new RpcRequest(); - rpcRequest.setMethodName("init"); - rpcRequest.setServiceConfig(new ServiceConfig()); - rpcRequest.setServiceClass(this.getClass()); - rpcRequest.setParams(new Object[] {"Test"}); - rpcRequest.setParamsTypes(new Class[] {String.class}); - rpcRequest.setProtocolName("brpc"); - rpcRequest.setAttachmentKv(kvMap); - - rpcResponse = new RpcResponse(); - rpcResponse.setResult("Test"); - rpcResponse.setStatus(Constants.SUCCESS_CODE); - rpcResponse.setErrorMsg(""); - rpcResponse.setProtocolName("brpc"); - rpcResponse.setAttachmentKv(kvMap); - } - - @Test - public void clientHandler() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - - Processor processor = new Processor() { - @Override - public ServiceRegistry getRegistry() { - return null; - } - - @Override - public void process(MsgBase msgBase, RpcChannel context) { - - } - - @Override - public void close() { - - } - - @Override - public void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory) { - - } - - @Override - public Integer waitTaskCount(String serviceKey) { - return 0; - } - - @Override - public Integer processingCount(String serviceKey) { - return 0; - } - - @Override - public Long completeCount(String serviceKey) { - return 0l; - } - - @Override - public Integer allWaitTaskCount() { - return 0; - } - }; - processor.setThreadPoolFactory(new ThreadPoolFactory() { - @Override - public ThreadPoolExecutor getThreadPool(RpcService rpcService) { - return null; - } - - @Override - public ThreadPoolExecutor getThreadPool() { - return null; - } - - @Override - public void close() { - - } - }); - NettyClient nettyClient = new NettyClient(builder.build()); - nettyClient.setProcessor(processor); - EmbeddedChannel channel = new EmbeddedChannel(new RpcHandler(nettyClient)); - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - channel.writeInbound(rpcResponse); - Assert.assertTrue(channel.readInbound() == null); - channel.finish(); - } - - @Test - public void serverHandler() { - URI.Builder builder = new URI.Builder("brpc", "localhost", 8006); - - Processor processor = Mockito.mock(Processor.class); - doNothing().when(processor).process(ArgumentMatchers.any(), ArgumentMatchers.any()); - NettyServer nettyServer = new NettyServer(builder.build()); - nettyServer.setProcessor(processor); - EmbeddedChannel channel = new EmbeddedChannel(new RpcHandler(nettyServer)); - try { - channel.writeInbound(rpcRequest); - } catch (Exception e) { - Assert.assertTrue(e instanceof TransportException); - } - - LongRpcChannel rpcChannel = new LongRpcChannel(channel, ChannelSide.CLIENT); - channel.attr(RpcChannel.ATTRIBUTE_KEY).set(new ChannelAttribute(rpcChannel)); - channel.writeInbound(rpcRequest); - Assert.assertTrue(channel.readInbound() == null); - channel.finish(); - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/ATestProtocol.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/ATestProtocol.java deleted file mode 100644 index 0a2e9931..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/ATestProtocol.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.protocol.test; - -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; -import com.baidu.cloud.starlight.api.protocol.Protocol; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.starlight.api.serialization.serializer.Serializer; -import com.baidu.cloud.starlight.serialization.serializer.ProtoStuffSerializer; - -public class ATestProtocol implements Protocol { - protected static final String PROTOCOL_NAME = "atest"; - protected static final Integer FIXED_LEN = 16; - protected static final byte[] MAGIC_HEAD = "Test".getBytes(); - - @Override - public ProtocolEncoder getEncoder() { - return null; - } - - @Override - public ProtocolDecoder getDecoder() { - return new TestDecoder(); - } - - @Override - public HeartbeatTrigger getHeartbeatTrigger() { - return new TestHeartbeatTrigger(); - } - - @Override - public Serializer getSerialize() { - return new ProtoStuffSerializer(); - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestDecoder.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestDecoder.java deleted file mode 100644 index 0c24450e..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestDecoder.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.protocol.test; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.AbstractMsgBase; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.transport.buffer.DynamicCompositeByteBuf; -import com.baidu.cloud.starlight.api.protocol.ProtocolDecoder; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; - -import java.util.Arrays; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class TestDecoder implements ProtocolDecoder { - @Override - public MsgBase decode(DynamicCompositeByteBuf input) throws CodecException { - // not enough data - if (input.readableBytes() < ATestProtocol.FIXED_LEN) { // not match - throw new CodecException(CodecException.PROTOCOL_INSUFFICIENT_DATA_EXCEPTION, - "Too little data to parse using Brpc"); // wait and retry - } - ByteBuf fixHeaderBuf = input.retainedSlice(ATestProtocol.FIXED_LEN); - try { - byte[] magic = new byte[4]; - fixHeaderBuf.readBytes(magic); - if (!Arrays.equals(magic, ATestProtocol.MAGIC_HEAD)) { // not match - throw new CodecException(CodecException.PROTOCOL_DECODE_NOTMATCH_EXCEPTION, - "Magic num dose not match Brpc"); - } - input.skipBytes(ATestProtocol.FIXED_LEN); - return new AbstractMsgBase() {}; - } finally { - if (fixHeaderBuf != null) { - fixHeaderBuf.release(); - } - } - } - - @Override - public void decodeBody(MsgBase msgBase) throws CodecException {} -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestEncoder.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestEncoder.java deleted file mode 100644 index 2fb86490..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestEncoder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.protocol.test; - -import com.baidu.cloud.starlight.api.exception.CodecException; -import com.baidu.cloud.starlight.api.model.MsgBase; -import com.baidu.cloud.starlight.api.protocol.ProtocolEncoder; -import com.baidu.cloud.thirdparty.netty.buffer.ByteBuf; - -/** - * Created by liuruisen on 2020/3/20. - */ -public class TestEncoder implements ProtocolEncoder { - @Override - public ByteBuf encode(MsgBase input) throws CodecException { - return null; - } - - @Override - public void encodeBody(MsgBase msgBase) throws CodecException {} -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestHeartbeatTrigger.java b/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestHeartbeatTrigger.java deleted file mode 100644 index 75696520..00000000 --- a/starlight/starlight-transport/src/test/java/com/baidu/cloud/starlight/transport/protocol/test/TestHeartbeatTrigger.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019 Baidu, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.baidu.cloud.starlight.transport.protocol.test; - -import com.baidu.cloud.starlight.api.common.Constants; -import com.baidu.cloud.starlight.api.model.Request; -import com.baidu.cloud.starlight.api.model.Response; -import com.baidu.cloud.starlight.api.model.RpcRequest; -import com.baidu.cloud.starlight.api.model.RpcResponse; -import com.baidu.cloud.starlight.api.protocol.HeartbeatTrigger; - -/** - * Created by liuruisen on 2020/3/23. - */ -public class TestHeartbeatTrigger implements HeartbeatTrigger { - @Override - public Request heartbeatRequest() { - RpcRequest request = new RpcRequest(); - request.setProtocolName(ATestProtocol.PROTOCOL_NAME); - request.setHeartbeat(true); - request.setParams(new Object[] {"ping"}); - request.setParamsTypes(new Class[] {String.class}); - return request; - } - - @Override - public Response heartbeatResponse() { - RpcResponse response = new RpcResponse(); - response.setProtocolName(ATestProtocol.PROTOCOL_NAME); - response.setHeartbeat(true); - response.setResult("pong"); - response.setStatus(Constants.SUCCESS_CODE); - return response; - } -} \ No newline at end of file diff --git a/starlight/starlight-transport/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol b/starlight/starlight-transport/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol deleted file mode 100644 index 28174f9e..00000000 --- a/starlight/starlight-transport/src/test/resources/META-INF/services/com.baidu.cloud.starlight.api.protocol.Protocol +++ /dev/null @@ -1 +0,0 @@ -com.baidu.cloud.starlight.transport.protocol.test.ATestProtocol \ No newline at end of file diff --git a/weixin_qrcode.png b/weixin_qrcode.png new file mode 100644 index 00000000..d9a48814 Binary files /dev/null and b/weixin_qrcode.png differ