云原生编程本质上涉及与远程端点的工作:微服务、无服务器、API、WebSocket、软件即服务 (SaaS) 应用等等。Ballerina 是一种云原生、通用、并发、事务性、静态和强类型编程语言,具有文本和图形语法。
它的专长是集成;它将分布式系统集成的基本概念、思想和工具引入到语言中,并提供类型安全、并发的环境来实现此类应用程序。这些包括分布式事务、弹性、并发性、安全性以及容器管理平台。
Ballerina 的灵感来自 Java、Go、C、C++、Rust、Haskell、Kotlin、Dart、TypeScript、JavaScript、Swift 和其他语言。它是一个开源项目,根据 Apache 2.0 许可证分发,您可以在该项目的 GitHub 存储库 中找到其源代码。
文本和图形语法
Ballerina 的编程语言语义旨在让开发人员自然地表达程序的结构和逻辑。为了描述多方之间复杂的交互,我们通常使用序列图。这种方法能够以直观的方式可视化端点和操作,例如异步和同步消息传递以及并行执行。

Ballerina 代码的文本和图形表示。
内置弹性
弹性和类型安全的集成内置于该语言中。当您尝试调用可能不可靠的外部端点时,您可以使用弹性功能(例如断路器、故障转移和重试)来规避该交互,用于您的特定协议。
断路器
添加断路器就像向您的客户端端点代码传递一些额外的参数一样简单。
endpoint http:Client backendClientEP {
url: "https://:8080",
// Circuit breaker configuration options
circuitBreaker: {
// Failure calculation window.
rollingWindow: {
// Time period in milliseconds for which the failure threshold
// is calculated.
timeWindowMillis: 10000,
// The granularity at which the time window slides.
// This is measured in milliseconds.
bucketSizeMillis: 2000
},
// The threshold for request failures.
// When this threshold exceeds, the circuit trips.
// This is the ratio between failures and total requests.
failureThreshold: 0.2,
// The time period(in milliseconds) to wait before
// attempting to make another request to the upstream service.
resetTimeMillis: 10000,
// HTTP response status codes which are considered as failures
statusCodes: [400, 404, 500]
},
timeoutMillis: 2000
};
故障转移
您可以定义需要故障转移的客户端端点,并设置超时间隔和故障转移代码。
// Define the failover client endpoint to call the backend services.
endpoint http:FailoverClient foBackendEP {
timeoutMillis: 5000,
failoverCodes: [501, 502, 503],
intervalMillis: 5000,
// Define set of HTTP Clients that needs to be Failover.
targets: [
{ url: "https://:3000/mock1" },
{ url: "https://:8080/echo" },
{ url: "https://:8080/mock" }
]
};
重试
您可以为您的端点定义端点重试配置,包括重试间隔、重试次数和退避因子。
endpoint http:Client backendClientEP {
url: "https://:8080",
// Retry configuration options.
retryConfig: {
interval: 3000,
count: 3,
backOffFactor: 0.5
},
timeoutMillis: 2000
};
异步和并行执行
Ballerina 的执行模型由称为 worker 的并行执行单元组成。worker 代表 Ballerina 的基本执行构造。在 Ballerina 中,每个函数都由一个或多个 worker 组成,这些 worker 是独立的并行执行代码块。如果 worker 块中没有明确提及 worker,则函数代码将属于单个隐式默认 worker。

并行执行代码的文本和图形表示。
Ballerina 还提供对 fork-join 的原生支持,它是 worker 交互的一种特殊情况。使用 fork-join,您可以 fork 逻辑并将执行卸载到多个 worker,并在 join 子句中有条件地连接所有 worker 的结果。
fork {
worker w1 {
int i = 23;
string s = "Foo";
io:println("[w1] i: ", i, " s: ", s);
(i, s) -> fork;
}
worker w2 {
float f = 10.344;
io:println("[w2] f: ", f);
f -> fork;
}
} join (all) (map results) {
int iW1;
}
Ballerina 还支持异步调用函数或端点。尽管 Ballerina 中大多数同步调用的外部端点都以完全非阻塞方式实现,但在某些情况下,您必须异步调用端点或函数,并在稍后检查结果。
future<http:Response | error> f1
= start nasdaqServiceEP
-> get("/nasdaq/quote/GOOG");
io:println(" >> Invocation completed!"
+ " Proceed without blocking for a response.");
// ‘await` blocks until the previously started async
// function returns.
var response = await f1;
事务处理
Ballerina 在处理事务方面具有语言级别的构造,您可以使用连接器执行本地事务,使用 X/A 兼容的连接器执行分布式事务,甚至可以使用语言运行时中可用的内置协调支持执行服务级别事务。
在 Ballerina 中,以事务方式执行一组操作只是将所有操作包装在“transaction”块中。
transaction {
_ = testDB->update("INSERT INTO CUSTOMER(ID,NAME) VALUES (1, 'Anne')");
_ = testDB->update("INSERT INTO SALARY (ID, MON_SALARY) VALUES (1, 2500)");
}
设计安全
Ballerina 的设计旨在确保使用 Ballerina 编写的程序本质上是安全的。Ballerina 程序可以抵御主要的安全性漏洞,包括 SQL 注入、路径操作、文件操作、未经授权的文件访问以及未验证的重定向(开放重定向)。这是通过污点分析机制实现的,Ballerina 编译器通过观察污点数据如何在程序中传播来识别不受信任(污点)的数据。如果将不受信任的数据传递给安全敏感的参数,则会生成编译器错误。
`@sensitive` 注解可以与用户自定义函数的参数一起使用。这允许用户限制将污点数据传递到安全敏感的参数中。
function userDefinedSecureOperation(@sensitive string secureParameter) {
}
例如,Ballerina 的污点检查机制通过禁止在 SQL 查询中使用污点数据,完全防止了 SQL 注入漏洞。以下代码会导致编译器错误,因为查询附加了用户提供的参数。
function main(string... args) {
table dataTable = check customerDBEP->
select("SELECT firstname FROM student WHERE registration_id = " +
args[0], null);
以下代码会导致编译器错误,因为用户提供的参数被传递给敏感参数。
userDefinedSecureOperation(args[0]);
在执行必要的验证和/或转义后,可以使用 `untaint` 一元表达式将后续值标记为受信任,并将其传递给敏感参数。
userDefinedSecureOperation(untaint args[0]);
原生支持 Docker 和 Kubernetes
Ballerina 理解其周围的架构;编译器具有环境感知能力,通过自动生成 Docker 镜像和 YAML,可以将微服务直接部署到 Docker 和 Kubernetes 等基础设施中。为了解释,让我们看一下示例 `hello_world.bal` 代码。
import ballerina/http;
import ballerinax/kubernetes;
@kubernetes:Service {
serviceType: "NodePort",
name: "hello-world"
}
endpoint http:Listener listener {
port: 9090
};
@kubernetes:Deployment {
image: "lakwarus/helloworld",
name: "hello-world"
}
@http:ServiceConfig {
basePath:"/"
}
service<http:Service> helloWorld bind listener {
@http:ResourceConfig {
path: "/"
}
sayHello(endpoint outboundEP, http:Request request) {
http:Response response = new;
response.setTextPayload("Hello World! \n");
_ = outboundEP->respond(response);
}
}
`@kubernetes:Service annotation` 定义了如何通过 Kubernetes 服务公开您的服务。`@kubernetes:Deployment` 通过捆绑应用程序代码来创建相应的 Docker 镜像,并使用 define-deployment 配置生成 Kubernetes 部署 YAML。
编译 `hello_world.bal` 文件将生成所有 Kubernetes 部署工件、Dockerfile 和 Docker 镜像。
$> ballerina build hello_world.bal
@kubernetes:Docker - complete 3/3
@kubernetes:Deployment - complete 1/1
@kubernetes:Service - complete 1/1
Run following command to deploy kubernetes artifacts:
kubectl apply -f ./kubernetes/
$> tree
.
├── hello_world.bal
├── hello_world.balx
└── kubernetes
├── docker
│ └── Dockerfile
├── hello_world_svc.yaml
└── hello_world_deployment.yaml
`kubectl apply -f ./kubernetes/` 将应用程序部署到 Kubernetes 中,并且可以通过 Kubernetes NodePort 访问。
$> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world NodePort 10.96.118.214 <none> 9090:32045/TCP 1m
$> curl https://:<32045>/
Hello, World!
Ballerina Central
Ballerina 通过其全球中央存储库 Ballerina Central 促进其软件包的重用和共享。在那里,您可以使用推送和拉取版本化的软件包来共享端点连接器、自定义注解和代码函数作为可共享的软件包。
了解更多
随着微服务架构的兴起,软件行业正在向云原生应用程序开发迈进。像 Ballerina 这样的云原生编程语言将成为快速创新的重要元素。
有关学习 Ballerina 的更多资源,请访问项目网站的 Learn Ballerina 部分。此外,请考虑参加 2018 年 7 月 18 日在旧金山举行并在全球直播的 Ballerinacon。这个为期一天的活动将提供关于微服务开发、弹性、集成、Docker 和 Kubernetes 部署、服务网格、无服务器、测试驱动的微服务开发、生命周期管理、可观察性和安全性的最佳实践的强化培训。OpenSource.com 的读者在 订购门票 时可以使用优惠码 BalCon-OpenSource 免费参加。
1 条评论